Site Characteristics

site_temps = full_data %>% 
  select(site, lat, season, doy, collection_temp, collection_salinity) %>%  
  distinct() %>% 
  filter(doy > 100) 

Copepods were collected by surface tow from sites across the Western Atlantic at several times throughout the year. The sites are shown below. Temperatures at the time of collection were measured using a manual thermometer. Across the entire set of collections, temperature ranged from 10°C to 36°C.

coords = site_data %>%
  select(site, long, lat) %>%
  distinct()

site_map = map_data("world") %>% 
  filter(region %in% c("USA", "Canada")) %>% 
  ggplot() + 
  geom_polygon(aes(x = long, y = lat, group = group),
               fill = "lightgrey") + 
  coord_map(xlim = c(-85,-60),
            ylim = c(25, 48)) + 
  geom_point(data = coords,
             mapping = aes(x = long, y = lat, colour = site),
             size = 3) +
  scale_colour_manual(values = site_cols) + 
  labs(x = "Longitude", 
       y = "Latitude") + 
  theme_matt(base_size = 16)

site_temp_plot = ggplot(site_temps, aes(x = doy, y = collection_temp, colour = site)) + 
  geom_line(linewidth = 2) + 
  geom_point(size = 5) +
  scale_colour_manual(values = site_cols) + 
  labs(y = "Temperature (°C)",
       x = "Day of the Year") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(site_map, site_temp_plot, common.legend = T, legend = "bottom")

Exact locations for the sites are provided here.

site_data %>%  
  arrange(lat) %>%  
  select("Site" = site, "Region" = region, "Lat" = lat, "Long" = long) %>% 
  knitr::kable(align = "c")
Site Region Lat Long
Key Largo Florida 25.28391 -80.33014
Manatee River Florida 27.50561 -82.57277
Ft. Hamer Florida 27.52488 -82.43101
Tyler Cove Maryland 38.35083 -76.22902
Ganey’s Wharf Maryland 38.80555 -75.90906
Esker Point Connecticut 41.32081 -72.00166
Sawyer Park Maine 43.90698 -69.87179
St. Thomas de Kent Wharf New Brunswick 46.44761 -64.63692
Ritchie Wharf New Brunswick 47.00481 -65.56291

Nested within each of the three regions (South, Central, and Northern regions) are pairs of low and high salinity sites:

data.frame("Region" = c("South", "Central", "North"),
           "Low Salinity" = c("Ft. Hamer", "Ganey's Wharf", "Ritchie Wharf"),
           "High Salinity" = c("Manatee River", "Tyler Cove", "St. Thomas de Kent Wharf")) %>% 
  knitr::kable(align = "c")
Region Low.Salinity High.Salinity
South Ft. Hamer Manatee River
Central Ganey’s Wharf Tyler Cove
North Ritchie Wharf St. Thomas de Kent Wharf

 

There are fairly well-established divergences between high salinity and low salinity populations of Acartia tonsa. These sets of geographically proximate but isolated populations provide independent comparisons of the effects of seasonality. Shown here are the collection conditions for these pairs of sites. Temperature was typically similar across the pairs within each collection, while salinity differences were fairly stable across collections.

season_cols = c("early" = "grey75", 
                "peak" = "grey50", 
                "late" = "grey25")

sal_regions = data.frame(region = rep(c("South", "Central", "North"), each = 2), 
                         site = c("Ft. Hamer", "Manatee River", 
                                  "Ganey's Wharf", "Tyler Cove", 
                                  "Ritchie Wharf", "St. Thomas de Kent Wharf"),
                         salinity = c("low", "high"))

sal_comps = full_data %>% 
  filter(site %in% sal_regions$site) %>% 
  inner_join(sal_regions, by = c("site")) %>% 
  select( region = region.y, site, salinity, season, doy, collection_temp, collection_salinity,
          size, ctmax, warming_tol) %>% 
  mutate(salinity = fct_relevel(salinity, "low", "high"),
         region = fct_relevel(region, "South", "Central", "North"))

sal_comp_temps = sal_comps %>%  
  select(salinity, season, region, collection_temp, collection_salinity) %>% 
  distinct() %>% 
  ggplot(aes(x = salinity, y = collection_temp, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_line(linewidth = 1.5) + 
  geom_point(size = 4) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Collection Temp. (°C)",
       x = "") + 
  theme_matt_facets(base_size = 14)

sal_comp_sal = sal_comps %>%  
  select(salinity, season, region, collection_temp, collection_salinity) %>% 
  distinct() %>% 
  ggplot(aes(x = salinity, y = collection_salinity, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_line(linewidth = 1.5) + 
  geom_point(size = 4) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Collection Salinity (psu)",
       x = "Salinity") + 
  theme_matt_facets(base_size = 14)

ggarrange(sal_comp_temps, sal_comp_sal, nrow = 2, common.legend = T, legend = "right")


# sal_comps %>%  
#   select(site, salinity, season, region, collection_temp, collection_salinity) %>% 
#   distinct() %>% 
#   ggplot(aes(x = collection_salinity, y = collection_temp, colour = site)) + 
#   facet_grid(region~.) + 
#   geom_point(size = 4) + 
#   #stat_ellipse() +
#   #geom_path(arrow = arrow(length = unit(0.1, "inches"), type = "closed")) + 
#   scale_colour_manual(values = site_cols) + 
#   theme_matt_facets(base_size = 14)

The latitudinal gradient covers a wide range of seasonality. Shown below is the temperature range. While based on collection temperatures, and therefore an underestimate of the total seasonal range of temperatures, these patterns are representative of the expected latitudinal gradient in seasonality.

site_temps %>% 
  group_by(site, lat) %>%  
  summarise(temp_range = max(collection_temp) - min(collection_temp)) %>%  
  ggplot(aes(x = lat, y = temp_range)) + 
  geom_point(aes(colour = site),
             size = 3) + 
  scale_color_manual(values = site_cols) + 
  labs(x = "Latitude", 
       y = "Collection Temp. Range (°C)") + 
  theme_matt() + 
  theme(legend.position = "right")

Phenotypic Measurements

Critical Thermal Limits

A total of 416 individuals were examined. Critical thermal limits and body size measurements were made before individuals were preserved in ethanol. We excluded data for 6 individuals, detailed below. These individuals had either very low CTmax or were, upon re-examination of photographs, identified as juveniles instead of mature females. With these individuals excluded, the full data set contains 410 phenotyped individuals.

excluded %>% 
  select(region, site, season, collection_temp, collection_salinity, replicate, tube, ctmax, size) %>% 
  knitr::kable(align = "c")
region site season collection_temp collection_salinity replicate tube ctmax size
Florida Manatee River peak 34.0 29 2 6 38.45833 0.616
Florida Manatee River peak 34.0 29 2 7 38.23750 0.593
Maryland Tyler Cove peak 29.5 15 2 2 36.84375 0.614
Connecticut Esker Point early 22.5 30 2 3 30.02604 0.687
Maine Sawyer Park peak 22.0 30 1 4 30.81424 0.865
New Brunswick St. Thomas de Kent Wharf late 13.5 28 1 3 28.78299 1.039

Critical thermal maxima (CTmax) was measured using a custom setup. The method uses a standard dynamic ramping assay to determine the maximum temperature individuals could sustain normal functioning. This differs from lethal temperatures, and indeed, all individuals observed so far recovered following the assay.

Individuals were rested for one hour after collection before the assay. During the assay, copepods were held in artificial seawater, composed of bottled spring water and Instant Ocean salt mix adjusted to match collection salinities. During the assay, several ‘control’ individuals were maintained in this solution at ambient temperatures without the temperature ramp to ensure that there was no background mortality. When sorting individuals from the plankton tow contents, they were held in a 50:50 mix of 60 um filtered water from the collection site and artificial seawater as an additional acclimation step.

Shown below are the measured CTmax values. Note: CTmax values for the early season Key Largo copepods were collected at the end of February 2023 as part of a separate project. Body size values were not measured during this project, nor were copepods individually preserved after the experiments. These early season CTmax values are included as a point of comparison. Individual measurements are shown in small points for each collection. The large points indicate the median values for each collection.

mean_ctmax = full_data %>% 
  group_by(site, season, doy, collection_temp) %>% 
  summarize(mean_ctmax = mean(ctmax),
            median_ctmax = median(ctmax))

ggplot(full_data, aes(x = season, y = ctmax, colour = site)) + 
  geom_line(data = mean_ctmax, 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_ctmax, 
             aes(y = median_ctmax),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

The same data is shown below, plotted against day of the year instead of season. This accounts for the variable timing of collections across regions (e.g. - the compressed collections from the Northern sites to accomodate the earlier onset of cold temperatures).

ggplot(filter(full_data, site != "Key Largo"), aes(x = doy, y = ctmax, colour = site)) + 
  geom_line(data = filter(mean_ctmax, site != "Key Largo"), 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = filter(mean_ctmax, site != "Key Largo"), 
             aes(y = median_ctmax),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

CTmax data for each individual site is shown below, plotted against day of the year. The grey line in each facet shows the collection temperatures. Note that both axes vary across facets.

ggplot(full_data, aes(x = doy, y = ctmax, colour = site)) + 
  facet_wrap(.~site, scales = "free") + 
  geom_line(data = mean_ctmax, 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_line(data = mean_ctmax, 
            aes(y = collection_temp, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 2,
            colour = "grey") + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Day of Year") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

Warming tolerance

Warming tolerance (the difference between thermal limits and environmental temperatures) is a commonly used metric of climate vulnerability. We calculated this as the difference between measured CTmax values and the collection temperature. Smaller warming tolerance values indicate that populations were nearer to their upper thermal limits, and may therefore be more vulnerable to additional warming.

mean_wt = full_data %>% 
  group_by(site, season) %>% 
  summarize(mean_wt = mean(warming_tol),
            median_wt = median(warming_tol))

ggplot(full_data, aes(x = season, y = warming_tol, colour = site)) + 
  geom_line(data = mean_wt, 
            aes(y = median_wt, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_wt, 
             aes(y = median_wt),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Warming Tolerance (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

Body Size

Following the CTmax assay, individuals were photographed for body size measurements. Prosome lengths were measured from these photographs using a scale micrometer and the software ImageJ. These measurements are shown below. As before, large points indicate the median body size.

mean_size = full_data %>% 
  group_by(site, season, doy, collection_temp) %>% 
  summarize(mean_size = mean(size),
            median_size = median(size))

ggplot(full_data, aes(x = season, y = size, colour = site)) + 
  geom_line(data = mean_size, 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_size, 
             aes(y = median_size),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) + 
  geom_line(data = drop_na(mean_size, mean_size), 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = drop_na(mean_size, mean_size), 
             aes(y = median_size),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) + 
  facet_wrap(.~site) + 
  geom_line(data = drop_na(mean_size, mean_size), 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Day of Year") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

Salinity Pair Comparisons

The three pairs of salinity comparisons do not show any general pattern, with variation dominated by seasonal changes.

sal_comp_ctmax_plot = sal_comps %>% 
  ggplot(aes(x = salinity, y = ctmax, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 2,
             position = position_dodge(width = 0.2)) + 
  #geom_line(size = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "CTmax (°C)",
       x = "") + 
  theme_matt_facets(base_size = 14)

sal_comp_size_plot = sal_comps %>% 
  ggplot(aes(x = salinity, y = size, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 2, 
             position = position_dodge(width = 0.2)) + 
  #geom_line(size = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "") + 
  theme_matt_facets(base_size = 14)

ggarrange(sal_comp_ctmax_plot, sal_comp_size_plot, nrow = 2, common.legend = T, legend = "right")


###

sal_comp_ctmax.model = lm(ctmax ~ collection_temp, data = sal_comps)
# summary(ctmax_temp.model)
# car::Anova(ctmax_temp.model)
sal_comp_ctmax_resids = residuals(sal_comp_ctmax.model)

sal_comp_size.model = lm(size ~ collection_temp, data = sal_comps)
# summary(size_temp.model)
# car::Anova(size_temp.model)
sal_comp_size_resids = residuals(sal_comp_size.model)

sal_comp_ctmax_resid_plot = sal_comps %>%
  mutate(ctmax_resids = sal_comp_ctmax_resids,
         size_resids = sal_comp_size_resids) %>%
  ggplot(aes(x = salinity, y = ctmax_resids, colour = season, group = season)) +
  facet_wrap(region~.) +
  geom_point(size = 2,
             position = position_dodge(width = 0.5)) +
  #geom_line(size = 1.5) +
  scale_colour_manual(values = season_cols) +
  labs(y = "CTmax \nResiduals",
       x = "") +
  theme_matt_facets(base_size = 14)

sal_comp_size_resid_plot = sal_comps %>%
  mutate(ctmax_resids = sal_comp_ctmax_resids,
         size_resids = sal_comp_size_resids) %>%
  ggplot(aes(x = salinity, y = size_resids, colour = season, group = season)) +
  facet_wrap(region~.) +
  geom_point(size = 2,
             position = position_dodge(width = 0.5)) +
  #geom_line(size = 1.5) +
  scale_colour_manual(values = season_cols) +
  labs(y = "Prosome Length \nResiduals",
       x = "") +
  theme_matt_facets(base_size = 14)

#ggarrange(sal_comp_ctmax_resid_plot, sal_comp_size_resid_plot, nrow = 2, common.legend = T, legend = "right")

Trait Correlations

We expect that collections from warmer waters should yield copepods with higher thermal limits and smaller body sizes. Our observations largely fit this expectation, with strong increases in CTmax at higher temperatures, and a general decrease in prosome lengths as temperature increased.

ctmax_temp_plot = ggplot(full_data, aes(x = collection_temp, y = ctmax)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "none")

size_temp_plot = ggplot(full_data, aes(x = collection_temp, y = size)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

wt_temp_plot = ggplot(full_data, aes(x = collection_temp, y = warming_tol)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Warming Tolerance (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(ctmax_temp_plot, wt_temp_plot, size_temp_plot, common.legend = T, legend = "bottom", nrow = 1)

Of particular interest is the relationship between prosome length and CTmax. In many cases, larger body sizes are associated with cold adaptation/acclimation. We may therefore see this pattern emerge across populations or seasons. If populations contain a mix of cold- and warm-adapted genotypes, however, we might also see this relationship emerge within populations or even individual collections. Shown below is the relationship between prosome length and CTmax in our data set. Individual regression lines for each site are also included - the dark grey lines in the background represent the ‘universal’ regression for that site, with individual colored regression lines for each collection.

universal_size = full_data %>% 
  ggplot(aes(x = size, y = ctmax)) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2,
              colour = "grey70") + 
  geom_point(aes(colour = site),
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right",
        axis.title.x = element_blank())

pop_size = full_data %>% 
  ggplot(aes(x = size, y = ctmax, colour = site, group = season)) + 
  facet_wrap(site~.) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_smooth(data = full_data, 
              aes(x = size, y = ctmax, group = site), 
              colour = "grey20", method = "lm", se = F) + 
  geom_point(size = 1.3, alpha = 0.3) + 
  geom_smooth(method = "lm", se = F,
              linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  scale_x_continuous(breaks = c(0.6, 0.8, 1)) + 
  labs(y = "CTmax (°C)",
       x = "Prosome Length (mm)") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right")

ggarrange(universal_size, pop_size, common.legend = T, legend = "none", nrow = 2)

This relationship may be affected by changes in temperature at each site, however, which is controlled for here by examining the relationship between CTmax and size residuals, acquired from regressions of these traits against collection temperature. This substantially reduces the strength of the apparent relationship, but there is still a slightly negative overall relationship.

filtered_data = full_data %>% 
  drop_na(size, ctmax)

ctmax_temp.model = lm(ctmax ~ collection_temp + site, data = filtered_data)
ctmax_resids = residuals(ctmax_temp.model)

size_temp.model = lm(size ~ collection_temp + site, data = filtered_data)
size_resids = residuals(size_temp.model)

universal_resids = filtered_data %>% 
  mutate(ctmax_resids = ctmax_resids,
         size_resids = size_resids) 

all_resids = ggplot(universal_resids, aes(x = size_resids, y = ctmax_resids)) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2,
              colour = "grey70") + 
  geom_point(aes(colour = site),
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Residuals",
       x = "") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right",
        axis.title.x = element_blank())

pop_resids = ggplot(universal_resids, aes(x = size_resids, y = ctmax_resids, colour = site, group = season)) + 
  facet_wrap(site~.) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_smooth(aes(x = size_resids, y = ctmax_resids, group = site), 
              colour = "grey20", method = "lm", se = F) + 
  geom_point(size = 1.3, alpha = 0.3) + 
  geom_smooth(method = "lm", se = F,
              linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Residuals",
       x = "Prosome Length Residuals") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right")

ggarrange(all_resids, pop_resids, common.legend = T, legend = "none", nrow = 2)

To more formally test the relationships between CTmax, collection temperature, and size, we used a linear mixed effects model, structured as ctmax ~ collection_temp + size + (1|site). This examines the effects of temperature and size on CTmax, with random intercepts for each site. Both fixed effects have a significant effect on CTmax. The overall effect of temperature suggests an increase in CTmax of 0.19°C per °C increase in collection temperature (i.e. - an ARR value of 0.19), while increasing body sizes decrease CTmax by -3.09°C per mm (or a decrease of ~-0.309°C per tenth of a mm, which is more biologically realistic for A. tonsa). This ARR value is slightly lower than observed for other copepod species, but well within the range of previously observed values. The estimated effect of body size is, as expected, similar to that from the residuals plot above.

ctmax.model = lme4::lmer(data = filtered_data, 
                         ctmax ~ collection_temp + size + (1|site))

#summary(ctmax.model)

effects_summary = data.frame(
  "Temperature" = unname(fixef(ctmax.model)["collection_temp"]),
  "Size" = unname(fixef(ctmax.model)["size"]))

knitr::kable(effects_summary)
Temperature Size
0.1900845 -3.08885

By extracting the conditional mode for the random effects, we can also examine how thermal limits vary across sites beyond the influence of collection temperatures and body sizes. Shown below are these values, extracted from the linear mixed effects model. We can see that, similar to what’s been observed in common garden experiments with A. tonsa previously, copepods from southern sites had higher thermal limits than those from northern sites. Interestingly, these population effects indicate that low salinity sites tended to have lower thermal limits than their paired high salinity site.

pop_effs = REsim(ctmax.model) %>% 
  dplyr::select("site" = groupID, term, mean, sd) %>% 
  filter(term == "(Intercept)") %>% 
  inner_join(site_data, by = c("site")) %>% 
  mutate(site = fct_reorder(site, lat))

#plotREsim(REsim(ctmax.model))  # plot the interval estimates

ggplot(pop_effs, aes(x = lat, y = mean, colour = site)) + 
  geom_hline(yintercept = 0) +
  geom_errorbar(aes(ymin = mean - 1.96 * sd, ymax = mean + 1.96 * sd),
                width = 0.5, linewidth = 1) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude", 
       y = "Population Effect") + 
  theme_matt() + 
  theme(legend.position = "right")

Trait Variability

Shown below is the trait variation (ranges) for each site. Ranges are calculated for each collection separately.

trait_ranges = full_data %>% 
  group_by(site, season, collection_temp, collection_salinity, doy, lat) %>% 
  summarise(mean_ctmax = mean(ctmax),
            ctmax_range = max(ctmax) - min(ctmax),
            ctmax_var = var(ctmax),
            mean_size = mean(size),
            size_range = max(size) - min(size),
            size_var = var(size)) %>% 
  mutate(prop_ctmax_range = ctmax_range / mean_ctmax,
         prop_size_range = size_range / mean_size)

ctmax_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_range, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Range (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ctmax_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_var, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Range (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

size_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_range, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Size Range (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

size_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_var, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Size Range (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(ctmax_range_temp, size_range_temp, common.legend = T, legend = "bottom")

Changes in trait variance may be indicative of phenotypic selection. If selection (as opposed to acclimation) are driving seasonal changes, we may expect to see a reduction in variance in the peak samples relative to the early season samples. Note that early season collection temperatures this year were higher than expected, driven by fairly strong heatwaves across the North Atlantic.

ggplot(trait_ranges, aes(x = season, y = ctmax_var, colour = site)) + 
  geom_line(aes(group = site), 
            linewidth = 1.5) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Variance",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

Comparing rates of change

Both CTmax and body size varied between sites and across seasons. It can be difficult to directly compare these two traits. We take two approaches to ease this comparison. Shown below is a comparison of the slopes from the trait regressions against collection temperature for each population, standardized by the standard deviation of the trait for each population (across all collections). This presents change per degree change in collection temperature in units of standard deviations for both CTmax and body size.

adj_slopes = full_data %>% 
  group_by(site, lat) %>% 
  arrange(doy) %>%  
  filter(site != "Key Largo") %>%
  summarize("ctmax_slope" = coef(lm(ctmax ~ collection_temp))["collection_temp"], 
            "mean_ctmax" = mean(ctmax),
            "ctmax_sd" = sd(ctmax),
            "size_slope" = coef(lm(size ~ collection_temp))["collection_temp"], 
            "mean_size" = mean(size),
            "size_sd" = sd(size), 
            "temp_range" = max(collection_temp) - min(collection_temp)) %>%  
  drop_na() %>% 
  mutate(adj_ctmax_slope = ctmax_slope / ctmax_sd,
         adj_size_slope = size_slope / size_sd) %>% 
  pivot_longer(cols = contains("_slope"), 
               names_to = "slope_type",
               values_to = "slope")

# ggplot(adj_slopes, aes(x = lat, y = temp_range)) + 
#   geom_point() + 
#   theme_matt()

ggplot(filter(adj_slopes, str_detect(slope_type, "adj_")), aes(x = slope_type, y = abs(slope), 
                       group = site, colour = site)) + 
  geom_hline(yintercept = 0) + 
  geom_line(linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "", 
       y = "Slope (absolute value)") + 
  theme_matt() + 
  theme(legend.position = "right",
        axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

Haldanes are a similar unit, representing change in units of standard deviations per generation. This can be a useful metric for comparing across traits, especially as the number of generations covered by our sampling period likely varies across populations. The calculation of haldanes is taken from Hendry and Kinnison (1999), which in turn is based on work from Gingerich (1993). We estimated the number of generations passed between collections using the empirical relationship between temperature and development time for Acartia tonsa from Leandro et al. (2006). For initial estimates, we used a temperature halfway between what was observed during collection. Changes were examined for each pair of collections (early to peak, and peak to late).

Shown below is a comparison of the estimated haldane values for CTmax and body size, separated by season. Keep in mind that while this metric accounts for differences in the number of generations between collections, it does not directly account for differences in temperature, leading to inflated values in the “peak to late” comparisons, which typically covered a larger range of temperatures.

early_peak = full_data %>% 
  filter(season %in% c("early", "peak")) %>% 
  mutate(season = if_else(season == "early", "one", "two")) %>% 
  group_by(site) %>% 
  mutate(ctmax_sd_p = sd(ctmax),
         size_sd_p = sd(size), 
         temp_change = max(collection_temp) - min(collection_temp),
         avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
         days_passed = max(doy) - min(doy)) %>% 
  select(site, lat, season, 
         ctmax_sd_p, size_sd_p, 
         temp_change, avg_temp, days_passed, 
         ctmax, size) %>%
  group_by(site, lat, season, 
           ctmax_sd_p, size_sd_p, 
           temp_change, avg_temp, days_passed) %>% 
  summarize(ctmax = mean(ctmax),
            size = mean(size)) %>% 
  pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p, 
                          temp_change, avg_temp, days_passed), 
              names_from = season, 
              values_from = c(ctmax, size)) %>% 
  mutate(season = "early_to_peak") %>%  
  drop_na()

peak_late = full_data %>% 
  filter(season %in% c("peak", "late")) %>% 
  mutate(season = if_else(season == "peak", "one", "two")) %>% 
  group_by(site) %>% 
  mutate(ctmax_sd_p = sd(ctmax),
         size_sd_p = sd(size), 
         temp_change = last(collection_temp) - first(collection_temp),
         avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
         days_passed = max(doy) - min(doy)) %>% 
  select(site, lat, season, ctmax_sd_p, size_sd_p, 
         temp_change, avg_temp, days_passed, 
         ctmax, size) %>%
  group_by(site, lat, season, ctmax_sd_p, size_sd_p, 
           temp_change, avg_temp, days_passed) %>% 
  summarize(ctmax = mean(ctmax),
            size = mean(size)) %>% 
  pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p, 
                          temp_change, avg_temp, days_passed), 
              names_from = season, 
              values_from = c(ctmax, size)) %>% 
  mutate(season = "peak_to_late") %>%  
  drop_na()

calc_halds = function(x1, x2, sd_p, g){
  ((x2 / sd_p) - (x1 / sd_p)) / g
}

haldanes = bind_rows(early_peak, peak_late) %>% 
  mutate("gen_time" = 5490*(avg_temp + 1)^-2.05, 
         "gens" = floor(days_passed / gen_time),
         "ctmax_haldanes" = calc_halds(x2 = ctmax_two, x1 = ctmax_one, 
                                       sd_p = ctmax_sd_p, g = gens),
         "size_haldanes" = calc_halds(x2 = size_two, x1 = size_one, 
                                      sd_p = size_sd_p, g = gens))

haldanes %>% 
  ungroup() %>% 
  select(site, temp_change, season, ctmax_haldanes, size_haldanes) %>% 
  pivot_longer(cols = c(ctmax_haldanes, size_haldanes),
               names_to = c("type", NA), 
               names_sep = "_",
               values_to = "haldanes") %>% 
  ggplot(aes(x = type, y = haldanes, group = site, colour = site)) + 
  facet_wrap(season~.) + 
  geom_hline(yintercept = 0) + 
  geom_line(aes(linewidth = desc(temp_change))) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Trait", 
       y = "Haldanes", 
       linewidth = "Temp. Change") + 
  theme_matt_facets()

Shown below are the haldane values plotted against latitude. Note that even though large changes in temperature occured between peak and late samples in the Chesapeake, the change in haldanes is relatively small, while in the Northern populations, changes are larger, though more variable.

ctmax_haldanes = ggplot(haldanes, aes(x = lat, y = ctmax_haldanes, colour = site, shape = season)) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude",
       y = "Change in CTmax (haldanes)") + 
  theme_matt_facets()

size_haldanes = ggplot(haldanes, aes(x = lat, y = size_haldanes, colour = site, shape = season)) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude",
       y = "Change in Size (haldanes)") + 
  theme_matt_facets()

ggarrange(ctmax_haldanes, size_haldanes, common.legend = T, legend = "right", nrow = 2)

Why does intraspecific data matter?

# Compare estimated warming tolerance "ranges" when: 1) CTmax for "average" collection is used; 2) When CTmax for one collection per population is used; and 3) When all collections are used. The idea is to show that not accounting for intra-specific and intra-population variation leads to incorrect predictions of vulnerability to warming because this variation can be substantial - across populations within each seasonal collection, there is at least 5°C variation in thermal limits, while across collections within populations, acclimation to changes in temperature can drive substantial variation. 

## Scenario 1 - single point estimates 

est_1 = full_data %>% 
  group_by(site, season) %>% 
  summarise("mean_ctmax" = mean(ctmax)) %>% 
  filter(site == "Tyler Cove", season == "peak")

scenario_1 = full_data %>% 
  mutate(rep_ctmax = est_1$mean_ctmax,
         pred_wt = rep_ctmax - collection_temp, 
         wt_diff = pred_wt - warming_tol)
  
ggplot(scenario_1, aes(x = lat, y = wt_diff)) + 
  facet_wrap(season~., nrow = 3) + 
  geom_hline(yintercept = 0) + 
  geom_point() + 
  labs(x = "Latitude", 
       y = "Predicted - Observed WT") + 
  theme_matt_facets()

Next Steps

After phenotyping, each individual was preserved in 95% ethanol. Individual DNA libraries will be prepared using Twist Bio 96-plex prep kits, then sequenced on an Illumina NovaSeq X Plus. Using the low-coverage whole genome sequences, we will examine seasonal patterns in allele frequency change, and compare these fine scale temporal patterns with the larger latitudinal patterns in allele frequency to determine whether the same alleles driving rapid seasonal adaptation are in play over larger spatial (and longer temporal) scales.

Misc. Details

ggplot(temp_record, aes(x = minute_passed, y = temp_C, group = factor(run))) + 
  geom_abline(slope = 0.3, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) + 
  geom_abline(slope = 0.1, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) + 
  geom_line(linewidth = 0.2, alpha = 0.8) + 
  geom_point(data = full_data, 
             aes(x = time, y = ctmax + 0.4),
             size = 2,
             shape = 25) +
  labs(x = "Time passed (minutes)",
       y = "Temperature (degrees C)",
       fill = "Trial Number") + 
  guides(colour = "none") + 
  theme_matt(base_size = 16) + 
  theme(legend.position = "right")

ramp_record2 = ramp_record %>% 
  group_by(run, minute_interval) %>% 
  summarise(mean_ramp = mean(ramp_per_minute)) %>% 
  ungroup()

ggplot(ramp_record2, aes(x = minute_interval, y = mean_ramp)) + 
  geom_hline(yintercept = 0.3) + 
  geom_hline(yintercept = 0.1) + 
  #geom_point() + 
  geom_hex(bins = 30) + 
  ylim(0, 0.35) + 
  labs(y = "Ramp Rate (deg. C / min.)",
       x = "Time into run (minute)") + 
  theme_matt(base_size = 16) 

full_data %>% 
  drop_na(replicate) %>%  
  ggplot(aes(x = factor(replicate), y = ctmax, group = site)) + 
  facet_grid(site~season, scales = "free_y") + 
  geom_point(position = position_jitter(width = 0.1, height = 0),
             alpha = 0.4,
             colour = "grey30") + 
  geom_smooth(method = "lm", colour = "black") + 
  labs(x = "Replicate", 
       y = "CTmax") + 
  theme_matt_facets()

ggplot(haldanes, aes(x = lat, y = gens, colour = site, shape = season)) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 5) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude", 
       y = "Generations between \ncollections") +
  scale_y_continuous(breaks = seq(from = 0, to = 11, by = 2)) + 
  theme_matt() + 
  theme(legend.position = "right")

obs_ranks = ggplot(full_data, aes(x = rank)) + 
  facet_wrap(tube~.) + 
  geom_histogram(binwidth = 1) + 
  scale_x_continuous(breaks = c(2,4,6,8,10)) + 
  ggtitle("Observation") + 
  theme_matt_facets()

sim_data = data.frame()
for(i in 1:max(full_data$run)){
  rep_data = data.frame("tube" = sample(c(1:10), size = 10, replace = F), 
           "rank" = c(1:10),
           "rep" = i) %>% 
  arrange(tube)
  
  sim_data = bind_rows(sim_data, rep_data)
  
}

sim_ranks = ggplot(sim_data, aes(x = rank)) + 
  facet_wrap(tube~.) + 
  geom_histogram(binwidth = 1) + 
  scale_x_continuous(breaks = c(2,4,6,8,10)) + 
  ggtitle("Simulation") + 
  theme_matt_facets()


ggarrange(obs_ranks, sim_ranks)

LS0tCnRpdGxlOiAiQ29tcGFyaW5nIHNlYXNvbmFsIGFuZCBsYXRpdHVkaW5hbCBwYXR0ZXJucyBpbiB0aGVybWFsIGFkYXB0YXRpb24iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3J9CiMgVE8gRE8gCiMgLSBUZW1wZXJhdHVyZSBwbG90cyBmb3IgY29udGV4dCAKIyAtIEFSUiBmb3IgJSBjaGFuZ2UgdG8gZGlyZWN0bHkgY29tcGFyZSB0cmFpdHMgCiMgLSBGcmFtZXdvcmsgZm9yIHF1YW50aWZ5aW5nIHRoZSBlZmZlY3RzIG9mIHdpdGhpbi0gYW5kIGFjcm9zcy1wb3B1bGF0aW9uIHZhcmlhdGlvbiBpbiB0aGVybWFsIGxpbWl0cyB0byBzcGF0aWFsIHBhdHRlcm5zIGluIHZ1bG5lcmFiaWxpdHkgdG8gd2FybWluZy4gQ29tcGFyaW5nIHByZWRpY3Rpb25zIGJhc2VkIG9uIDEpIG1lZGlhbiwgMikgb3ZlcmFsbCBDVG1heCB2cy4gdGVtcCByZWdyZXNzaW9uLCAzKSBwb3B1bGF0aW9uIHZhcmlhdGlvbiBpbiBpbnRlcmNlcHRzLCA0KSBwb3B1bGF0aW9uIHZhcmlhdGlvbiBpbiBib3RoIHNsb3BlIGFuZCBpbnRlcmNlcHQKYGBgCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBlY2hvID0gRn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0ga25pdHI6OmlzX2h0bWxfb3V0cHV0KCksCiAgZmlnLmFsaWduID0gImNlbnRlciIsCiAgZmlnLnBhdGggPSAiLi4vRmlndXJlcy9tYXJrZG93bi8iLAogIGRldiA9IGMoInBuZyIsICJwZGYiKSwKICBtZXNzYWdlID0gRkFMU0UsCiAgd2FybmluZyA9IEZBTFNFLAogIGNvbGxhcHNlID0gVAopCgp0aGVtZV9tYXR0ID0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTgsCiAgICAgICAgICAgICAgICAgICAgICBkYXJrX3RleHQgPSAiZ3JleTIwIil7CiAgbWlkX3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVsyXQogIGxpZ2h0X3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVszXQogIAogIHRoZW1lX3B1YnIoYmFzZV9mYW1pbHk9InNhbnMiKSAlK3JlcGxhY2UlIAogICAgdGhlbWUoCiAgICAgIHBhbmVsLmJhY2tncm91bmQgID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZGFya190ZXh0KSwKICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtaWRfdGV4dCksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDMsIDAsIDAsIDApLCAibW0iKSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsIDUsIDAsIDApLCAibW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1iYXNlX3NpemUgKiAwLjkpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSwiY20iKQogICAgKQp9Cgp0aGVtZV9tYXR0X2ZhY2V0cyA9IGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgdGhlbWVfYncoYmFzZV9mYW1pbHk9InNhbnMiKSAlK3JlcGxhY2UlIAogICAgdGhlbWUoCiAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUpLAogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBkYXJrX3RleHQpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IG1pZF90ZXh0KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMywgMCwgMCwgMCksICJtbSIpKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwgNSwgMCwgMCksICJtbSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ2xlID0gOTApLAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPWJhc2Vfc2l6ZSAqIDAuOSksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMC45LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLjI1LCAwLjI1LCAwLjI1LCAwLjI1LCJjbSIpCiAgICApCn0KCnNpdGVfY29scyA9IGMoIktleSBMYXJnbyIgPSAiaW5kaWFucmVkNCIsIAogICAgICAgICAgICAgICJNYW5hdGVlIFJpdmVyIiA9ICJjb3JhbCIsIAogICAgICAgICAgICAgICJGdC4gSGFtZXIiID0gImNvcmFsMyIsCiAgICAgICAgICAgICAgIlR5bGVyIENvdmUiID0gImdvbGRlbnJvZDEiLAogICAgICAgICAgICAgICJHYW5leSdzIFdoYXJmIiA9ICJkYXJrZ29sZGVucm9kMyIsIAogICAgICAgICAgICAgICJFc2tlciBQb2ludCIgPSAiZGFya3NlYWdyZWVuMyIsCiAgICAgICAgICAgICAgIlNhd3llciBQYXJrIiA9ICJwYWxlZ3JlZW40IiwgCiAgICAgICAgICAgICAgIlN0LiBUaG9tYXMgZGUgS2VudCBXaGFyZiIgPSAic3RlZWxibHVlMiIsCiAgICAgICAgICAgICAgIlJpdGNoaWUgV2hhcmYiID0gInN0ZWVsYmx1ZTQiKQpgYGAKCiMjIFNpdGUgQ2hhcmFjdGVyaXN0aWNzCgpgYGB7cn0Kc2l0ZV90ZW1wcyA9IGZ1bGxfZGF0YSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSkgJT4lICAKICBkaXN0aW5jdCgpICU+JSAKICBmaWx0ZXIoZG95ID4gMTAwKSAKYGBgCgpDb3BlcG9kcyB3ZXJlIGNvbGxlY3RlZCBieSBzdXJmYWNlIHRvdyBmcm9tIHNpdGVzIGFjcm9zcyB0aGUgV2VzdGVybiBBdGxhbnRpYyBhdCBzZXZlcmFsIHRpbWVzIHRocm91Z2hvdXQgdGhlIHllYXIuIFRoZSBzaXRlcyBhcmUgc2hvd24gYmVsb3cuIFRlbXBlcmF0dXJlcyBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uIHdlcmUgbWVhc3VyZWQgdXNpbmcgYSBtYW51YWwgdGhlcm1vbWV0ZXIuIEFjcm9zcyB0aGUgZW50aXJlIHNldCBvZiBjb2xsZWN0aW9ucywgdGVtcGVyYXR1cmUgcmFuZ2VkIGZyb20gYHIgbWluKHNpdGVfdGVtcHMkY29sbGVjdGlvbl90ZW1wKWDCsEMgdG8gYHIgbWF4KHNpdGVfdGVtcHMkY29sbGVjdGlvbl90ZW1wKWDCsEMuCgpgYGB7ciBzaXRlLWNoYXJzLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KY29vcmRzID0gc2l0ZV9kYXRhICU+JQogIHNlbGVjdChzaXRlLCBsb25nLCBsYXQpICU+JQogIGRpc3RpbmN0KCkKCnNpdGVfbWFwID0gbWFwX2RhdGEoIndvcmxkIikgJT4lIAogIGZpbHRlcihyZWdpb24gJWluJSBjKCJVU0EiLCAiQ2FuYWRhIikpICU+JSAKICBnZ3Bsb3QoKSArIAogIGdlb21fcG9seWdvbihhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLAogICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Z3JleSIpICsgCiAgY29vcmRfbWFwKHhsaW0gPSBjKC04NSwtNjApLAogICAgICAgICAgICB5bGltID0gYygyNSwgNDgpKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGNvb3JkcywKICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGNvbG91ciA9IHNpdGUpLAogICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTG9uZ2l0dWRlIiwgCiAgICAgICB5ID0gIkxhdGl0dWRlIikgKyAKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE2KQoKc2l0ZV90ZW1wX3Bsb3QgPSBnZ3Bsb3Qoc2l0ZV90ZW1wcywgYWVzKHggPSBkb3ksIHkgPSBjb2xsZWN0aW9uX3RlbXAsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAyKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgICAgeCA9ICJEYXkgb2YgdGhlIFllYXIiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShzaXRlX21hcCwgc2l0ZV90ZW1wX3Bsb3QsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpFeGFjdCBsb2NhdGlvbnMgZm9yIHRoZSBzaXRlcyBhcmUgcHJvdmlkZWQgaGVyZS4gCgpgYGB7ciBzaXRlLXRhYmxlfQpzaXRlX2RhdGEgJT4lICAKICBhcnJhbmdlKGxhdCkgJT4lICAKICBzZWxlY3QoIlNpdGUiID0gc2l0ZSwgIlJlZ2lvbiIgPSByZWdpb24sICJMYXQiID0gbGF0LCAiTG9uZyIgPSBsb25nKSAlPiUgCiAga25pdHI6OmthYmxlKGFsaWduID0gImMiKQpgYGAKCk5lc3RlZCB3aXRoaW4gZWFjaCBvZiB0aGUgdGhyZWUgcmVnaW9ucyAoU291dGgsIENlbnRyYWwsIGFuZCBOb3J0aGVybiByZWdpb25zKSBhcmUgcGFpcnMgb2YgbG93IGFuZCBoaWdoIHNhbGluaXR5IHNpdGVzOiAgICAKCmBgYHtyIHNhbC10YWJsZX0KZGF0YS5mcmFtZSgiUmVnaW9uIiA9IGMoIlNvdXRoIiwgIkNlbnRyYWwiLCAiTm9ydGgiKSwKICAgICAgICAgICAiTG93IFNhbGluaXR5IiA9IGMoIkZ0LiBIYW1lciIsICJHYW5leSdzIFdoYXJmIiwgIlJpdGNoaWUgV2hhcmYiKSwKICAgICAgICAgICAiSGlnaCBTYWxpbml0eSIgPSBjKCJNYW5hdGVlIFJpdmVyIiwgIlR5bGVyIENvdmUiLCAiU3QuIFRob21hcyBkZSBLZW50IFdoYXJmIikpICU+JSAKICBrbml0cjo6a2FibGUoYWxpZ24gPSAiYyIpCmBgYAoKXCAKClRoZXJlIGFyZSBmYWlybHkgd2VsbC1lc3RhYmxpc2hlZCBkaXZlcmdlbmNlcyBiZXR3ZWVuIGhpZ2ggc2FsaW5pdHkgYW5kIGxvdyBzYWxpbml0eSBwb3B1bGF0aW9ucyBvZiAqQWNhcnRpYSB0b25zYSouIFRoZXNlIHNldHMgb2YgZ2VvZ3JhcGhpY2FsbHkgcHJveGltYXRlIGJ1dCBpc29sYXRlZCBwb3B1bGF0aW9ucyBwcm92aWRlIGluZGVwZW5kZW50IGNvbXBhcmlzb25zIG9mIHRoZSBlZmZlY3RzIG9mIHNlYXNvbmFsaXR5LiBTaG93biBoZXJlIGFyZSB0aGUgY29sbGVjdGlvbiBjb25kaXRpb25zIGZvciB0aGVzZSBwYWlycyBvZiBzaXRlcy4gVGVtcGVyYXR1cmUgd2FzIHR5cGljYWxseSBzaW1pbGFyIGFjcm9zcyB0aGUgcGFpcnMgd2l0aGluIGVhY2ggY29sbGVjdGlvbiwgd2hpbGUgc2FsaW5pdHkgZGlmZmVyZW5jZXMgd2VyZSBmYWlybHkgc3RhYmxlIGFjcm9zcyBjb2xsZWN0aW9ucy4gCgpgYGB7ciBzZWFzb24tc2FsLWNvbXBzLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD04fQpzZWFzb25fY29scyA9IGMoImVhcmx5IiA9ICJncmV5NzUiLCAKICAgICAgICAgICAgICAgICJwZWFrIiA9ICJncmV5NTAiLCAKICAgICAgICAgICAgICAgICJsYXRlIiA9ICJncmV5MjUiKQoKc2FsX3JlZ2lvbnMgPSBkYXRhLmZyYW1lKHJlZ2lvbiA9IHJlcChjKCJTb3V0aCIsICJDZW50cmFsIiwgIk5vcnRoIiksIGVhY2ggPSAyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXRlID0gYygiRnQuIEhhbWVyIiwgIk1hbmF0ZWUgUml2ZXIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHYW5leSdzIFdoYXJmIiwgIlR5bGVyIENvdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSaXRjaGllIFdoYXJmIiwgIlN0LiBUaG9tYXMgZGUgS2VudCBXaGFyZiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgc2FsaW5pdHkgPSBjKCJsb3ciLCAiaGlnaCIpKQoKc2FsX2NvbXBzID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc2l0ZSAlaW4lIHNhbF9yZWdpb25zJHNpdGUpICU+JSAKICBpbm5lcl9qb2luKHNhbF9yZWdpb25zLCBieSA9IGMoInNpdGUiKSkgJT4lIAogIHNlbGVjdCggcmVnaW9uID0gcmVnaW9uLnksIHNpdGUsIHNhbGluaXR5LCBzZWFzb24sIGRveSwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5LAogICAgICAgICAgc2l6ZSwgY3RtYXgsIHdhcm1pbmdfdG9sKSAlPiUgCiAgbXV0YXRlKHNhbGluaXR5ID0gZmN0X3JlbGV2ZWwoc2FsaW5pdHksICJsb3ciLCAiaGlnaCIpLAogICAgICAgICByZWdpb24gPSBmY3RfcmVsZXZlbChyZWdpb24sICJTb3V0aCIsICJDZW50cmFsIiwgIk5vcnRoIikpCgpzYWxfY29tcF90ZW1wcyA9IHNhbF9jb21wcyAlPiUgIAogIHNlbGVjdChzYWxpbml0eSwgc2Vhc29uLCByZWdpb24sIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gY29sbGVjdGlvbl90ZW1wLCBjb2xvdXIgPSBzZWFzb24sIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjUpICsgCiAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwKICAgICAgIHggPSAiIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCnNhbF9jb21wX3NhbCA9IHNhbF9jb21wcyAlPiUgIAogIHNlbGVjdChzYWxpbml0eSwgc2Vhc29uLCByZWdpb24sIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gY29sbGVjdGlvbl9zYWxpbml0eSwgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMS41KSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzZWFzb25fY29scykgKyAKICBsYWJzKHkgPSAiQ29sbGVjdGlvbiBTYWxpbml0eSAocHN1KSIsCiAgICAgICB4ID0gIlNhbGluaXR5IikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCmdnYXJyYW5nZShzYWxfY29tcF90ZW1wcywgc2FsX2NvbXBfc2FsLCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIpCgojIHNhbF9jb21wcyAlPiUgIAojICAgc2VsZWN0KHNpdGUsIHNhbGluaXR5LCBzZWFzb24sIHJlZ2lvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5KSAlPiUgCiMgICBkaXN0aW5jdCgpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fc2FsaW5pdHksIHkgPSBjb2xsZWN0aW9uX3RlbXAsIGNvbG91ciA9IHNpdGUpKSArIAojICAgZmFjZXRfZ3JpZChyZWdpb25+LikgKyAKIyAgIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsgCiMgICAjc3RhdF9lbGxpcHNlKCkgKwojICAgI2dlb21fcGF0aChhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4xLCAiaW5jaGVzIiksIHR5cGUgPSAiY2xvc2VkIikpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKIyAgIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE0KQpgYGAKClRoZSBsYXRpdHVkaW5hbCBncmFkaWVudCBjb3ZlcnMgYSB3aWRlIHJhbmdlIG9mIHNlYXNvbmFsaXR5LiBTaG93biBiZWxvdyBpcyB0aGUgdGVtcGVyYXR1cmUgcmFuZ2UuIFdoaWxlIGJhc2VkIG9uIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzLCBhbmQgdGhlcmVmb3JlIGFuIHVuZGVyZXN0aW1hdGUgb2YgdGhlIHRvdGFsIHNlYXNvbmFsIHJhbmdlIG9mIHRlbXBlcmF0dXJlcywgdGhlc2UgcGF0dGVybnMgYXJlIHJlcHJlc2VudGF0aXZlIG9mIHRoZSBleHBlY3RlZCBsYXRpdHVkaW5hbCBncmFkaWVudCBpbiBzZWFzb25hbGl0eS4gCgpgYGB7ciBsYXQtdGVtcC1yYW5nZS1wbG90LCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQpzaXRlX3RlbXBzICU+JSAKICBncm91cF9ieShzaXRlLCBsYXQpICU+JSAgCiAgc3VtbWFyaXNlKHRlbXBfcmFuZ2UgPSBtYXgoY29sbGVjdGlvbl90ZW1wKSAtIG1pbihjb2xsZWN0aW9uX3RlbXApKSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGxhdCwgeSA9IHRlbXBfcmFuZ2UpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLAogICAgICAgICAgICAgc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLCAKICAgICAgIHkgPSAiQ29sbGVjdGlvbiBUZW1wLiBSYW5nZSAowrBDKSIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgoKIyMgUGhlbm90eXBpYyBNZWFzdXJlbWVudHMgCgojIyMgQ3JpdGljYWwgVGhlcm1hbCBMaW1pdHMKCkEgdG90YWwgb2YgYHIgZGltKGFsbF9kYXRhKVsxXWAgaW5kaXZpZHVhbHMgd2VyZSBleGFtaW5lZC4gQ3JpdGljYWwgdGhlcm1hbCBsaW1pdHMgYW5kIGJvZHkgc2l6ZSBtZWFzdXJlbWVudHMgd2VyZSBtYWRlIGJlZm9yZSBpbmRpdmlkdWFscyB3ZXJlIHByZXNlcnZlZCBpbiBldGhhbm9sLiBXZSBleGNsdWRlZCBkYXRhIGZvciBgciBkaW0oZXhjbHVkZWQpWzFdYCBpbmRpdmlkdWFscywgZGV0YWlsZWQgYmVsb3cuIFRoZXNlIGluZGl2aWR1YWxzIGhhZCBlaXRoZXIgdmVyeSBsb3cgQ1RtYXggb3Igd2VyZSwgdXBvbiByZS1leGFtaW5hdGlvbiBvZiBwaG90b2dyYXBocywgaWRlbnRpZmllZCBhcyBqdXZlbmlsZXMgaW5zdGVhZCBvZiBtYXR1cmUgZmVtYWxlcy4gV2l0aCB0aGVzZSBpbmRpdmlkdWFscyBleGNsdWRlZCwgKip0aGUgZnVsbCBkYXRhIHNldCBjb250YWlucyBgciBkaW0oZnVsbF9kYXRhKVsxXWAgcGhlbm90eXBlZCBpbmRpdmlkdWFscyoqLiAgIAoKYGBge3IgZXhjbHVkZWQtaW5kc30KZXhjbHVkZWQgJT4lIAogIHNlbGVjdChyZWdpb24sIHNpdGUsIHNlYXNvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5LCByZXBsaWNhdGUsIHR1YmUsIGN0bWF4LCBzaXplKSAlPiUgCiAga25pdHI6OmthYmxlKGFsaWduID0gImMiKQpgYGAKCkNyaXRpY2FsIHRoZXJtYWwgbWF4aW1hIChDVG1heCkgd2FzIG1lYXN1cmVkIHVzaW5nIGEgY3VzdG9tIHNldHVwLiBUaGUgbWV0aG9kIHVzZXMgYSBzdGFuZGFyZCBkeW5hbWljIHJhbXBpbmcgYXNzYXkgdG8gZGV0ZXJtaW5lIHRoZSBtYXhpbXVtIHRlbXBlcmF0dXJlIGluZGl2aWR1YWxzIGNvdWxkIHN1c3RhaW4gbm9ybWFsIGZ1bmN0aW9uaW5nLiBUaGlzIGRpZmZlcnMgZnJvbSBsZXRoYWwgdGVtcGVyYXR1cmVzLCBhbmQgaW5kZWVkLCBhbGwgaW5kaXZpZHVhbHMgb2JzZXJ2ZWQgc28gZmFyIHJlY292ZXJlZCBmb2xsb3dpbmcgdGhlIGFzc2F5LgoKSW5kaXZpZHVhbHMgd2VyZSByZXN0ZWQgZm9yIG9uZSBob3VyIGFmdGVyIGNvbGxlY3Rpb24gYmVmb3JlIHRoZSBhc3NheS4gRHVyaW5nIHRoZSBhc3NheSwgY29wZXBvZHMgd2VyZSBoZWxkIGluIGFydGlmaWNpYWwgc2Vhd2F0ZXIsIGNvbXBvc2VkIG9mIGJvdHRsZWQgc3ByaW5nIHdhdGVyIGFuZCBJbnN0YW50IE9jZWFuIHNhbHQgbWl4IGFkanVzdGVkIHRvIG1hdGNoIGNvbGxlY3Rpb24gc2FsaW5pdGllcy4gRHVyaW5nIHRoZSBhc3NheSwgc2V2ZXJhbCAnY29udHJvbCcgaW5kaXZpZHVhbHMgd2VyZSBtYWludGFpbmVkIGluIHRoaXMgc29sdXRpb24gYXQgYW1iaWVudCB0ZW1wZXJhdHVyZXMgd2l0aG91dCB0aGUgdGVtcGVyYXR1cmUgcmFtcCB0byBlbnN1cmUgdGhhdCB0aGVyZSB3YXMgbm8gYmFja2dyb3VuZCBtb3J0YWxpdHkuIFdoZW4gc29ydGluZyBpbmRpdmlkdWFscyBmcm9tIHRoZSBwbGFua3RvbiB0b3cgY29udGVudHMsIHRoZXkgd2VyZSBoZWxkIGluIGEgNTA6NTAgbWl4IG9mIDYwIHVtIGZpbHRlcmVkIHdhdGVyIGZyb20gdGhlIGNvbGxlY3Rpb24gc2l0ZSBhbmQgYXJ0aWZpY2lhbCBzZWF3YXRlciBhcyBhbiBhZGRpdGlvbmFsIGFjY2xpbWF0aW9uIHN0ZXAuIAoKU2hvd24gYmVsb3cgYXJlIHRoZSBtZWFzdXJlZCBDVG1heCB2YWx1ZXMuIE5vdGU6IENUbWF4IHZhbHVlcyBmb3IgdGhlIGVhcmx5IHNlYXNvbiBLZXkgTGFyZ28gY29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgdGhlIGVuZCBvZiBGZWJydWFyeSAyMDIzIGFzIHBhcnQgb2YgYSBzZXBhcmF0ZSBwcm9qZWN0LiBCb2R5IHNpemUgdmFsdWVzIHdlcmUgbm90IG1lYXN1cmVkIGR1cmluZyB0aGlzIHByb2plY3QsIG5vciB3ZXJlIGNvcGVwb2RzIGluZGl2aWR1YWxseSBwcmVzZXJ2ZWQgYWZ0ZXIgdGhlIGV4cGVyaW1lbnRzLiBUaGVzZSBlYXJseSBzZWFzb24gQ1RtYXggdmFsdWVzIGFyZSBpbmNsdWRlZCBhcyBhIHBvaW50IG9mIGNvbXBhcmlzb24uIEluZGl2aWR1YWwgbWVhc3VyZW1lbnRzIGFyZSBzaG93biBpbiBzbWFsbCBwb2ludHMgZm9yIGVhY2ggY29sbGVjdGlvbi4gVGhlIGxhcmdlIHBvaW50cyBpbmRpY2F0ZSB0aGUgbWVkaWFuIHZhbHVlcyBmb3IgZWFjaCBjb2xsZWN0aW9uLiAKCmBgYHtyIHNlYXNvbmFsLWN0LW1heH0KbWVhbl9jdG1heCA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIHN1bW1hcml6ZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIG1lZGlhbl9jdG1heCA9IG1lZGlhbihjdG1heCkpCgpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fY3RtYXgpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKVGhlIHNhbWUgZGF0YSBpcyBzaG93biBiZWxvdywgcGxvdHRlZCBhZ2FpbnN0IGRheSBvZiB0aGUgeWVhciBpbnN0ZWFkIG9mIHNlYXNvbi4gVGhpcyBhY2NvdW50cyBmb3IgdGhlIHZhcmlhYmxlIHRpbWluZyBvZiBjb2xsZWN0aW9ucyBhY3Jvc3MgcmVnaW9ucyAoZS5nLiAtIHRoZSBjb21wcmVzc2VkIGNvbGxlY3Rpb25zIGZyb20gdGhlIE5vcnRoZXJuIHNpdGVzIHRvIGFjY29tb2RhdGUgdGhlIGVhcmxpZXIgb25zZXQgb2YgY29sZCB0ZW1wZXJhdHVyZXMpLiAKCmBgYHtyIGRveS1jdC1tYXh9CmdncGxvdChmaWx0ZXIoZnVsbF9kYXRhLCBzaXRlICE9ICJLZXkgTGFyZ28iKSwgYWVzKHggPSBkb3ksIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBmaWx0ZXIobWVhbl9jdG1heCwgc2l0ZSAhPSAiS2V5IExhcmdvIiksIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihtZWFuX2N0bWF4LCBzaXRlICE9ICJLZXkgTGFyZ28iKSwgCiAgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpDVG1heCBkYXRhIGZvciBlYWNoIGluZGl2aWR1YWwgc2l0ZSBpcyBzaG93biBiZWxvdywgcGxvdHRlZCBhZ2FpbnN0IGRheSBvZiB0aGUgeWVhci4gVGhlIGdyZXkgbGluZSBpbiBlYWNoIGZhY2V0IHNob3dzIHRoZSBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlcy4gTm90ZSB0aGF0IGJvdGggYXhlcyB2YXJ5IGFjcm9zcyBmYWNldHMuICAKCmBgYHtyIGN0bWF4LWluZC1wb3BzLWRveSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBkb3ksIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gY29sbGVjdGlvbl90ZW1wLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJEYXkgb2YgWWVhciIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIGN0bWF4LWluZC1wb3BzLXNlYXNvbiwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NiwgaW5jbHVkZSA9IEZ9CmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gc2Vhc29uLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlLCBzY2FsZXMgPSAiZnJlZV95IikgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gY29sbGVjdGlvbl90ZW1wLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgoKIyMjIFdhcm1pbmcgdG9sZXJhbmNlCgpXYXJtaW5nIHRvbGVyYW5jZSAodGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGVybWFsIGxpbWl0cyBhbmQgZW52aXJvbm1lbnRhbCB0ZW1wZXJhdHVyZXMpIGlzIGEgY29tbW9ubHkgdXNlZCBtZXRyaWMgb2YgY2xpbWF0ZSB2dWxuZXJhYmlsaXR5LiBXZSBjYWxjdWxhdGVkIHRoaXMgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtZWFzdXJlZCBDVG1heCB2YWx1ZXMgYW5kIHRoZSBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLiBTbWFsbGVyIHdhcm1pbmcgdG9sZXJhbmNlIHZhbHVlcyBpbmRpY2F0ZSB0aGF0IHBvcHVsYXRpb25zIHdlcmUgbmVhcmVyIHRvIHRoZWlyIHVwcGVyIHRoZXJtYWwgbGltaXRzLCBhbmQgbWF5IHRoZXJlZm9yZSBiZSBtb3JlIHZ1bG5lcmFibGUgdG8gYWRkaXRpb25hbCB3YXJtaW5nLiAKCmBgYHtyIHNlYXNvbmFsLXdhcm1pbmctdG9sfQptZWFuX3d0ID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzaXRlLCBzZWFzb24pICU+JSAKICBzdW1tYXJpemUobWVhbl93dCA9IG1lYW4od2FybWluZ190b2wpLAogICAgICAgICAgICBtZWRpYW5fd3QgPSBtZWRpYW4od2FybWluZ190b2wpKQoKZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBzZWFzb24sIHkgPSB3YXJtaW5nX3RvbCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX3d0LCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fd3QsIGdyb3VwID0gc2l0ZSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3BvaW50KGRhdGEgPSBtZWFuX3d0LCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX3d0KSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIldhcm1pbmcgVG9sZXJhbmNlICjCsEMpIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCiMjIyBCb2R5IFNpemUKCkZvbGxvd2luZyB0aGUgQ1RtYXggYXNzYXksIGluZGl2aWR1YWxzIHdlcmUgcGhvdG9ncmFwaGVkIGZvciBib2R5IHNpemUgbWVhc3VyZW1lbnRzLiBQcm9zb21lIGxlbmd0aHMgd2VyZSBtZWFzdXJlZCBmcm9tIHRoZXNlIHBob3RvZ3JhcGhzIHVzaW5nIGEgc2NhbGUgbWljcm9tZXRlciBhbmQgdGhlIHNvZnR3YXJlIEltYWdlSi4gVGhlc2UgbWVhc3VyZW1lbnRzIGFyZSBzaG93biBiZWxvdy4gQXMgYmVmb3JlLCBsYXJnZSBwb2ludHMgaW5kaWNhdGUgdGhlIG1lZGlhbiBib2R5IHNpemUuIAoKYGBge3Igc2Vhc29uYWwtYm9keS1zaXplfQptZWFuX3NpemUgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsIHNlYXNvbiwgZG95LCBjb2xsZWN0aW9uX3RlbXApICU+JSAKICBzdW1tYXJpemUobWVhbl9zaXplID0gbWVhbihzaXplKSwKICAgICAgICAgICAgbWVkaWFuX3NpemUgPSBtZWRpYW4oc2l6ZSkpCgpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9zaXplLCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fc2l6ZSwgCiAgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplKSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKYGBge3IgZG95LWJvZHktc2l6ZX0KZ2dwbG90KGRyb3BfbmEoZnVsbF9kYXRhLCBzaXplKSwgYWVzKHggPSBkb3ksIHkgPSBzaXplLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGRyb3BfbmEobWVhbl9zaXplLCBtZWFuX3NpemUpLCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGRyb3BfbmEobWVhbl9zaXplLCBtZWFuX3NpemUpLCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX3NpemUpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpgYGB7ciBzaXplLWluZC1wb3BzLWRveSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGRyb3BfbmEoZnVsbF9kYXRhLCBzaXplKSwgYWVzKHggPSBkb3ksIHkgPSBzaXplLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGRyb3BfbmEobWVhbl9zaXplLCBtZWFuX3NpemUpLCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIkRheSBvZiBZZWFyIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKCmBgYHtyIHNpemUtaW5kLXBvcHMtc2Vhc29uLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02LCBpbmNsdWRlID0gRn0KZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBzZWFzb24sIHkgPSBzaXplLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fc2l6ZSwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX3NpemUsIGdyb3VwID0gc2l0ZSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICBsaW5ld2lkdGggPSAzLCBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjgpICsgCiAgIyBnZW9tX3BvaW50KGRhdGEgPSBtZWFuX2N0bWF4LCAKICAjICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fY3RtYXgpLAogICMgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAjICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgojIyMgU2FsaW5pdHkgUGFpciBDb21wYXJpc29ucyAKClRoZSB0aHJlZSBwYWlycyBvZiBzYWxpbml0eSBjb21wYXJpc29ucyBkbyBub3Qgc2hvdyBhbnkgZ2VuZXJhbCBwYXR0ZXJuLCB3aXRoIHZhcmlhdGlvbiBkb21pbmF0ZWQgYnkgc2Vhc29uYWwgY2hhbmdlcy4gCgpgYGB7ciBzYWwtcGFpci10cmFpdHN9CnNhbF9jb21wX2N0bWF4X3Bsb3QgPSBzYWxfY29tcHMgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gY3RtYXgsIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAocmVnaW9ufi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjIpKSArIAogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpzYWxfY29tcF9zaXplX3Bsb3QgPSBzYWxfY29tcHMgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gc2l6ZSwgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjIpKSArIAogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCmdnYXJyYW5nZShzYWxfY29tcF9jdG1heF9wbG90LCBzYWxfY29tcF9zaXplX3Bsb3QsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKCiMjIwoKc2FsX2NvbXBfY3RtYXgubW9kZWwgPSBsbShjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCwgZGF0YSA9IHNhbF9jb21wcykKIyBzdW1tYXJ5KGN0bWF4X3RlbXAubW9kZWwpCiMgY2FyOjpBbm92YShjdG1heF90ZW1wLm1vZGVsKQpzYWxfY29tcF9jdG1heF9yZXNpZHMgPSByZXNpZHVhbHMoc2FsX2NvbXBfY3RtYXgubW9kZWwpCgpzYWxfY29tcF9zaXplLm1vZGVsID0gbG0oc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCwgZGF0YSA9IHNhbF9jb21wcykKIyBzdW1tYXJ5KHNpemVfdGVtcC5tb2RlbCkKIyBjYXI6OkFub3ZhKHNpemVfdGVtcC5tb2RlbCkKc2FsX2NvbXBfc2l6ZV9yZXNpZHMgPSByZXNpZHVhbHMoc2FsX2NvbXBfc2l6ZS5tb2RlbCkKCnNhbF9jb21wX2N0bWF4X3Jlc2lkX3Bsb3QgPSBzYWxfY29tcHMgJT4lCiAgbXV0YXRlKGN0bWF4X3Jlc2lkcyA9IHNhbF9jb21wX2N0bWF4X3Jlc2lkcywKICAgICAgICAgc2l6ZV9yZXNpZHMgPSBzYWxfY29tcF9zaXplX3Jlc2lkcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBjdG1heF9yZXNpZHMsIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKwogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsKICBsYWJzKHkgPSAiQ1RtYXggXG5SZXNpZHVhbHMiLAogICAgICAgeCA9ICIiKSArCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpzYWxfY29tcF9zaXplX3Jlc2lkX3Bsb3QgPSBzYWxfY29tcHMgJT4lCiAgbXV0YXRlKGN0bWF4X3Jlc2lkcyA9IHNhbF9jb21wX2N0bWF4X3Jlc2lkcywKICAgICAgICAgc2l6ZV9yZXNpZHMgPSBzYWxfY29tcF9zaXplX3Jlc2lkcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBzaXplX3Jlc2lkcywgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArCiAgI2dlb21fbGluZShzaXplID0gMS41KSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzZWFzb25fY29scykgKwogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCBcblJlc2lkdWFscyIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCiNnZ2FycmFuZ2Uoc2FsX2NvbXBfY3RtYXhfcmVzaWRfcGxvdCwgc2FsX2NvbXBfc2l6ZV9yZXNpZF9wbG90LCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIpCmBgYAoKCiMjIFRyYWl0IENvcnJlbGF0aW9ucwoKV2UgZXhwZWN0IHRoYXQgY29sbGVjdGlvbnMgZnJvbSB3YXJtZXIgd2F0ZXJzIHNob3VsZCB5aWVsZCBjb3BlcG9kcyB3aXRoIGhpZ2hlciB0aGVybWFsIGxpbWl0cyBhbmQgc21hbGxlciBib2R5IHNpemVzLiBPdXIgb2JzZXJ2YXRpb25zIGxhcmdlbHkgZml0IHRoaXMgZXhwZWN0YXRpb24sIHdpdGggc3Ryb25nIGluY3JlYXNlcyBpbiBDVG1heCBhdCBoaWdoZXIgdGVtcGVyYXR1cmVzLCBhbmQgYSBnZW5lcmFsIGRlY3JlYXNlIGluIHByb3NvbWUgbGVuZ3RocyBhcyB0ZW1wZXJhdHVyZSBpbmNyZWFzZWQuIAoKYGBge3IgdGVtcC1jb3JzLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9Nn0KY3RtYXhfdGVtcF9wbG90ID0gZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpzaXplX3RlbXBfcGxvdCA9IGdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgp3dF90ZW1wX3Bsb3QgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHdhcm1pbmdfdG9sKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2UoY3RtYXhfdGVtcF9wbG90LCB3dF90ZW1wX3Bsb3QsIHNpemVfdGVtcF9wbG90LCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gImJvdHRvbSIsIG5yb3cgPSAxKQpgYGAKCmBgYHtyIGluY2x1ZGUgPSBGfQpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4KSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoKT2YgcGFydGljdWxhciBpbnRlcmVzdCBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJvc29tZSBsZW5ndGggYW5kIENUbWF4LiBJbiBtYW55IGNhc2VzLCBsYXJnZXIgYm9keSBzaXplcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGNvbGQgYWRhcHRhdGlvbi9hY2NsaW1hdGlvbi4gV2UgbWF5IHRoZXJlZm9yZSBzZWUgdGhpcyBwYXR0ZXJuIGVtZXJnZSBhY3Jvc3MgcG9wdWxhdGlvbnMgb3Igc2Vhc29ucy4gSWYgcG9wdWxhdGlvbnMgY29udGFpbiBhIG1peCBvZiBjb2xkLSBhbmQgd2FybS1hZGFwdGVkIGdlbm90eXBlcywgaG93ZXZlciwgd2UgbWlnaHQgYWxzbyBzZWUgdGhpcyByZWxhdGlvbnNoaXAgZW1lcmdlICoqd2l0aGluKiogcG9wdWxhdGlvbnMgb3IgZXZlbiBpbmRpdmlkdWFsIGNvbGxlY3Rpb25zLiBTaG93biBiZWxvdyBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJvc29tZSBsZW5ndGggYW5kIENUbWF4IGluIG91ciBkYXRhIHNldC4gSW5kaXZpZHVhbCByZWdyZXNzaW9uIGxpbmVzIGZvciBlYWNoIHNpdGUgYXJlIGFsc28gaW5jbHVkZWQgLSB0aGUgZGFyayBncmV5IGxpbmVzIGluIHRoZSBiYWNrZ3JvdW5kIHJlcHJlc2VudCB0aGUgJ3VuaXZlcnNhbCcgcmVncmVzc2lvbiBmb3IgdGhhdCBzaXRlLCB3aXRoIGluZGl2aWR1YWwgY29sb3JlZCByZWdyZXNzaW9uIGxpbmVzIGZvciBlYWNoIGNvbGxlY3Rpb24uICAgIAoKYGBge3IgY3RtYXgtdnMtc2l6ZSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9MTB9CnVuaXZlcnNhbF9zaXplID0gZnVsbF9kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpKSArIAogICMgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIGN0bWF4ID4gMzEpLCAKICAjICAgICAgICAgICAgIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4KSwKICAjICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICMgICAgICAgICAgICAgY29sb3VyID0gImdyZXk2MCIsIAogICMgICAgICAgICAgICAgc2UgPSBGLAogICMgICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTcwIikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICIiKSArCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBvcF9zaXplID0gZnVsbF9kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaXplLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNpdGUsIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHNpdGV+LikgKyAKICAjIGdlb21fc21vb3RoKGRhdGEgPSBmaWx0ZXIoZnVsbF9kYXRhLCBjdG1heCA+IDMxKSwgCiAgIyAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgIyAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCAKICAjICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NjAiLCAKICAjICAgICAgICAgICAgIHNlID0gRiwKICAjICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGZ1bGxfZGF0YSwgCiAgICAgICAgICAgICAgYWVzKHggPSBzaXplLCB5ID0gY3RtYXgsIGdyb3VwID0gc2l0ZSksIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5MjAiLCBtZXRob2QgPSAibG0iLCBzZSA9IEYpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMS4zLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLjYsIDAuOCwgMSkpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiUHJvc29tZSBMZW5ndGggKG1tKSIpICsKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE0KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2UodW5pdmVyc2FsX3NpemUsIHBvcF9zaXplLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gIm5vbmUiLCBucm93ID0gMikKYGBgCgpUaGlzIHJlbGF0aW9uc2hpcCBtYXkgYmUgYWZmZWN0ZWQgYnkgY2hhbmdlcyBpbiB0ZW1wZXJhdHVyZSBhdCBlYWNoIHNpdGUsIGhvd2V2ZXIsIHdoaWNoIGlzIGNvbnRyb2xsZWQgZm9yIGhlcmUgYnkgZXhhbWluaW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBDVG1heCBhbmQgc2l6ZSByZXNpZHVhbHMsIGFjcXVpcmVkIGZyb20gcmVncmVzc2lvbnMgb2YgdGhlc2UgdHJhaXRzIGFnYWluc3QgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gVGhpcyBzdWJzdGFudGlhbGx5IHJlZHVjZXMgdGhlIHN0cmVuZ3RoIG9mIHRoZSBhcHBhcmVudCByZWxhdGlvbnNoaXAsIGJ1dCB0aGVyZSBpcyBzdGlsbCBhIHNsaWdodGx5IG5lZ2F0aXZlIG92ZXJhbGwgcmVsYXRpb25zaGlwLiAgICAgCgpgYGB7ciBjdG1heC12cy1zaXplLXJlc2lkcywgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9MTB9CmZpbHRlcmVkX2RhdGEgPSBmdWxsX2RhdGEgJT4lIAogIGRyb3BfbmEoc2l6ZSwgY3RtYXgpCgpjdG1heF90ZW1wLm1vZGVsID0gbG0oY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBzaXRlLCBkYXRhID0gZmlsdGVyZWRfZGF0YSkKY3RtYXhfcmVzaWRzID0gcmVzaWR1YWxzKGN0bWF4X3RlbXAubW9kZWwpCgpzaXplX3RlbXAubW9kZWwgPSBsbShzaXplIH4gY29sbGVjdGlvbl90ZW1wICsgc2l0ZSwgZGF0YSA9IGZpbHRlcmVkX2RhdGEpCnNpemVfcmVzaWRzID0gcmVzaWR1YWxzKHNpemVfdGVtcC5tb2RlbCkKCnVuaXZlcnNhbF9yZXNpZHMgPSBmaWx0ZXJlZF9kYXRhICU+JSAKICBtdXRhdGUoY3RtYXhfcmVzaWRzID0gY3RtYXhfcmVzaWRzLAogICAgICAgICBzaXplX3Jlc2lkcyA9IHNpemVfcmVzaWRzKSAKCmFsbF9yZXNpZHMgPSBnZ3Bsb3QodW5pdmVyc2FsX3Jlc2lkcywgYWVzKHggPSBzaXplX3Jlc2lkcywgeSA9IGN0bWF4X3Jlc2lkcykpICsgCiAgIyBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKGZ1bGxfZGF0YSwgY3RtYXggPiAzMSksIAogICMgICAgICAgICAgICAgYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpLAogICMgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgIyAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTYwIiwgCiAgIyAgICAgICAgICAgICBzZSA9IEYsCiAgIyAgICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NzAiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLAogICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBSZXNpZHVhbHMiLAogICAgICAgeCA9ICIiKSArCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBvcF9yZXNpZHMgPSBnZ3Bsb3QodW5pdmVyc2FsX3Jlc2lkcywgYWVzKHggPSBzaXplX3Jlc2lkcywgeSA9IGN0bWF4X3Jlc2lkcywgY29sb3VyID0gc2l0ZSwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAoc2l0ZX4uKSArIAogICMgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIGN0bWF4ID4gMzEpLCAKICAjICAgICAgICAgICAgIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4KSwKICAjICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICMgICAgICAgICAgICAgY29sb3VyID0gImdyZXk2MCIsIAogICMgICAgICAgICAgICAgc2UgPSBGLAogICMgICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3Ntb290aChhZXMoeCA9IHNpemVfcmVzaWRzLCB5ID0gY3RtYXhfcmVzaWRzLCBncm91cCA9IHNpdGUpLCAKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTIwIiwgbWV0aG9kID0gImxtIiwgc2UgPSBGKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDEuMywgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4IFJlc2lkdWFscyIsCiAgICAgICB4ID0gIlByb3NvbWUgTGVuZ3RoIFJlc2lkdWFscyIpICsKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE0KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2UoYWxsX3Jlc2lkcywgcG9wX3Jlc2lkcywgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJub25lIiwgbnJvdyA9IDIpCmBgYAoKYGBge3IgY3RtYXgtbW9kZWwsIGluY2x1ZGUgPSBGfQojIAojIGZ1bGwubW9kZWwgPSBsbShkYXRhID0gZmlsdGVyZWRfZGF0YSwgCiMgICAgICAgICAgICAgICAgIGN0bWF4IH4gc2l0ZSAqIGNvbGxlY3Rpb25fdGVtcCAqIHNpemUsIAojICAgICAgICAgICAgICAgICAgICBuYS5hY3Rpb24gPSAibmEuZmFpbCIpCiMgCiMgZHJlZGdlX3Jlc3VsdHMgPSBNdU1Jbjo6ZHJlZGdlKGZ1bGwubW9kZWwpCiMgdG9wX21vZGVsID0gTXVNSW46OmdldC5tb2RlbHMoZHJlZGdlX3Jlc3VsdHMsIDEpW1sxXV0gI0Jlc3QgbW9kZWwKIyAKIyB0ZW1wX3ZhbHMgPSBhc190aWJibGUoZW10cmVuZHModG9wX21vZGVsLCBzcGVjID0gInNpdGUiLCB2YXIgPSAiY29sbGVjdGlvbl90ZW1wIikpIAojIHNpemVfdmFscyA9IGFzX3RpYmJsZShlbXRyZW5kcyh0b3BfbW9kZWwsIHNwZWMgPSAic2l0ZSIsIHZhciA9ICJzaXplIikpIAoKYGBgCgpUbyBtb3JlIGZvcm1hbGx5IHRlc3QgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBDVG1heCwgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSwgYW5kIHNpemUsIHdlIHVzZWQgYSBsaW5lYXIgbWl4ZWQgZWZmZWN0cyBtb2RlbCwgc3RydWN0dXJlZCBhcyBgY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBzaXplICsgKDF8c2l0ZSlgLiBUaGlzIGV4YW1pbmVzIHRoZSBlZmZlY3RzIG9mIHRlbXBlcmF0dXJlIGFuZCBzaXplIG9uIENUbWF4LCB3aXRoIHJhbmRvbSBpbnRlcmNlcHRzIGZvciBlYWNoIHNpdGUuIEJvdGggZml4ZWQgZWZmZWN0cyBoYXZlIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIENUbWF4LiBUaGUgb3ZlcmFsbCBlZmZlY3Qgb2YgdGVtcGVyYXR1cmUgc3VnZ2VzdHMgYW4gaW5jcmVhc2UgaW4gQ1RtYXggb2YgYHIgcm91bmQodW5uYW1lKGZpeGVmKGN0bWF4Lm1vZGVsKVsiY29sbGVjdGlvbl90ZW1wIl0pLCBkaWdpdHMgPSAyKWDCsEMgcGVyIMKwQyBpbmNyZWFzZSBpbiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIChpLmUuIC0gYW4gQVJSIHZhbHVlIG9mIGByIHJvdW5kKHVubmFtZShmaXhlZihjdG1heC5tb2RlbClbImNvbGxlY3Rpb25fdGVtcCJdKSwgZGlnaXRzID0gMilgKSwgd2hpbGUgaW5jcmVhc2luZyBib2R5IHNpemVzIGRlY3JlYXNlIENUbWF4IGJ5IGByIHJvdW5kKHVubmFtZShmaXhlZihjdG1heC5tb2RlbClbInNpemUiXSksIGRpZ2l0cyA9IDIpYMKwQyBwZXIgbW0gKG9yIGEgZGVjcmVhc2Ugb2YgfmByIHJvdW5kKHVubmFtZShmaXhlZihjdG1heC5tb2RlbClbInNpemUiXSksIGRpZ2l0cyA9IDIpLzEwYMKwQyBwZXIgdGVudGggb2YgYSBtbSwgd2hpY2ggaXMgbW9yZSBiaW9sb2dpY2FsbHkgcmVhbGlzdGljIGZvciAqQS4gdG9uc2EqKS4gVGhpcyBBUlIgdmFsdWUgaXMgc2xpZ2h0bHkgbG93ZXIgdGhhbiBvYnNlcnZlZCBmb3Igb3RoZXIgY29wZXBvZCBzcGVjaWVzLCBidXQgd2VsbCB3aXRoaW4gdGhlIHJhbmdlIG9mIHByZXZpb3VzbHkgb2JzZXJ2ZWQgdmFsdWVzLiBUaGUgZXN0aW1hdGVkIGVmZmVjdCBvZiBib2R5IHNpemUgaXMsIGFzIGV4cGVjdGVkLCBzaW1pbGFyIHRvIHRoYXQgZnJvbSB0aGUgcmVzaWR1YWxzIHBsb3QgYWJvdmUuIAoKYGBge3J9CmN0bWF4Lm1vZGVsID0gbG1lNDo6bG1lcihkYXRhID0gZmlsdGVyZWRfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCArIHNpemUgKyAoMXxzaXRlKSkKCiNzdW1tYXJ5KGN0bWF4Lm1vZGVsKQoKZWZmZWN0c19zdW1tYXJ5ID0gZGF0YS5mcmFtZSgKICAiVGVtcGVyYXR1cmUiID0gdW5uYW1lKGZpeGVmKGN0bWF4Lm1vZGVsKVsiY29sbGVjdGlvbl90ZW1wIl0pLAogICJTaXplIiA9IHVubmFtZShmaXhlZihjdG1heC5tb2RlbClbInNpemUiXSkpCgprbml0cjo6a2FibGUoZWZmZWN0c19zdW1tYXJ5KQpgYGAKCkJ5IGV4dHJhY3RpbmcgdGhlIGNvbmRpdGlvbmFsIG1vZGUgZm9yIHRoZSByYW5kb20gZWZmZWN0cywgd2UgY2FuIGFsc28gZXhhbWluZSBob3cgdGhlcm1hbCBsaW1pdHMgdmFyeSBhY3Jvc3Mgc2l0ZXMgYmV5b25kIHRoZSBpbmZsdWVuY2Ugb2YgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMgYW5kIGJvZHkgc2l6ZXMuIFNob3duIGJlbG93IGFyZSB0aGVzZSB2YWx1ZXMsIGV4dHJhY3RlZCBmcm9tIHRoZSBsaW5lYXIgbWl4ZWQgZWZmZWN0cyBtb2RlbC4gV2UgY2FuIHNlZSB0aGF0LCBzaW1pbGFyIHRvIHdoYXQncyBiZWVuIG9ic2VydmVkIGluIGNvbW1vbiBnYXJkZW4gZXhwZXJpbWVudHMgd2l0aCAqQS4gdG9uc2EqIHByZXZpb3VzbHksIGNvcGVwb2RzIGZyb20gc291dGhlcm4gc2l0ZXMgaGFkIGhpZ2hlciB0aGVybWFsIGxpbWl0cyB0aGFuIHRob3NlIGZyb20gbm9ydGhlcm4gc2l0ZXMuIEludGVyZXN0aW5nbHksIHRoZXNlIHBvcHVsYXRpb24gZWZmZWN0cyBpbmRpY2F0ZSB0aGF0IGxvdyBzYWxpbml0eSBzaXRlcyB0ZW5kZWQgdG8gaGF2ZSBsb3dlciB0aGVybWFsIGxpbWl0cyB0aGFuIHRoZWlyIHBhaXJlZCBoaWdoIHNhbGluaXR5IHNpdGUuIAoKYGBge3IgcG9wLWVmZnMtcGxvdCwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Nn0KcG9wX2VmZnMgPSBSRXNpbShjdG1heC5tb2RlbCkgJT4lIAogIGRwbHlyOjpzZWxlY3QoInNpdGUiID0gZ3JvdXBJRCwgdGVybSwgbWVhbiwgc2QpICU+JSAKICBmaWx0ZXIodGVybSA9PSAiKEludGVyY2VwdCkiKSAlPiUgCiAgaW5uZXJfam9pbihzaXRlX2RhdGEsIGJ5ID0gYygic2l0ZSIpKSAlPiUgCiAgbXV0YXRlKHNpdGUgPSBmY3RfcmVvcmRlcihzaXRlLCBsYXQpKQoKI3Bsb3RSRXNpbShSRXNpbShjdG1heC5tb2RlbCkpICAjIHBsb3QgdGhlIGludGVydmFsIGVzdGltYXRlcwoKZ2dwbG90KHBvcF9lZmZzLCBhZXMoeCA9IGxhdCwgeSA9IG1lYW4sIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbiAtIDEuOTYgKiBzZCwgeW1heCA9IG1lYW4gKyAxLjk2ICogc2QpLAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjUsIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLCAKICAgICAgIHkgPSAiUG9wdWxhdGlvbiBFZmZlY3QiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKCiMjIFRyYWl0IFZhcmlhYmlsaXR5CgpTaG93biBiZWxvdyBpcyB0aGUgdHJhaXQgdmFyaWF0aW9uIChyYW5nZXMpIGZvciBlYWNoIHNpdGUuIFJhbmdlcyBhcmUgY2FsY3VsYXRlZCBmb3IgZWFjaCBjb2xsZWN0aW9uIHNlcGFyYXRlbHkuCgpgYGB7ciB0cmFpdC1yYW5nZS1wbG90fQp0cmFpdF9yYW5nZXMgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsIHNlYXNvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5LCBkb3ksIGxhdCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIGN0bWF4X3JhbmdlID0gbWF4KGN0bWF4KSAtIG1pbihjdG1heCksCiAgICAgICAgICAgIGN0bWF4X3ZhciA9IHZhcihjdG1heCksCiAgICAgICAgICAgIG1lYW5fc2l6ZSA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgIHNpemVfcmFuZ2UgPSBtYXgoc2l6ZSkgLSBtaW4oc2l6ZSksCiAgICAgICAgICAgIHNpemVfdmFyID0gdmFyKHNpemUpKSAlPiUgCiAgbXV0YXRlKHByb3BfY3RtYXhfcmFuZ2UgPSBjdG1heF9yYW5nZSAvIG1lYW5fY3RtYXgsCiAgICAgICAgIHByb3Bfc2l6ZV9yYW5nZSA9IHNpemVfcmFuZ2UgLyBtZWFuX3NpemUpCgpjdG1heF9yYW5nZV90ZW1wID0gZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heF9yYW5nZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggUmFuZ2UgKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpjdG1heF92YXJfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gY3RtYXhfdmFyLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBSYW5nZSAowrBDKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnNpemVfcmFuZ2VfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZV9yYW5nZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiU2l6ZSBSYW5nZSAobW0pIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKc2l6ZV92YXJfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZV92YXIsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlNpemUgUmFuZ2UgKG1tKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjdG1heF9yYW5nZV90ZW1wLCBzaXplX3JhbmdlX3RlbXAsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpDaGFuZ2VzIGluIHRyYWl0IHZhcmlhbmNlIG1heSBiZSBpbmRpY2F0aXZlIG9mIHBoZW5vdHlwaWMgc2VsZWN0aW9uLiBJZiBzZWxlY3Rpb24gKGFzIG9wcG9zZWQgdG8gYWNjbGltYXRpb24pIGFyZSBkcml2aW5nIHNlYXNvbmFsIGNoYW5nZXMsIHdlIG1heSBleHBlY3QgdG8gc2VlIGEgcmVkdWN0aW9uIGluIHZhcmlhbmNlIGluIHRoZSBwZWFrIHNhbXBsZXMgcmVsYXRpdmUgdG8gdGhlIGVhcmx5IHNlYXNvbiBzYW1wbGVzLiBOb3RlIHRoYXQgZWFybHkgc2Vhc29uIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzIHRoaXMgeWVhciB3ZXJlIGhpZ2hlciB0aGFuIGV4cGVjdGVkLCBkcml2ZW4gYnkgZmFpcmx5IHN0cm9uZyBoZWF0d2F2ZXMgYWNyb3NzIHRoZSBOb3J0aCBBdGxhbnRpYy4gICAgCgpgYGB7ciBzZWFzb24tdmFyfQpnZ3Bsb3QodHJhaXRfcmFuZ2VzLCBhZXMoeCA9IHNlYXNvbiwgeSA9IGN0bWF4X3ZhciwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNpdGUpLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMS41KSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4IFZhcmlhbmNlIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIHZhci1jaGFuZ2UtdGVtcC1jaGFuZ2UsIGluY2x1ZGUgPSBGfQp2YXJfY2hhbmdlX2RhdGEgPSB0cmFpdF9yYW5nZXMgJT4lICAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShtZWFuX3d0ID0gbWVhbl9jdG1heCAtIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBhcnJhbmdlKHNpdGUsIGRveSkgJT4lICAKICBtdXRhdGUodGVtcF9jaGFuZ2UgPSBjb2xsZWN0aW9uX3RlbXAgLSBsYWcoY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgY3RtYXhfY2hhbmdlID0gbWVhbl9jdG1heCAtIGxhZyhtZWFuX2N0bWF4KSwKICAgICAgICAgd3RfY2hhbmdlID0gbWVhbl93dCAtIGxhZyhtZWFuX3d0KSwKICAgICAgICAgdmFyX2NoYW5nZSA9IGN0bWF4X3ZhciAtIGxhZyhjdG1heF92YXIpKSAlPiUgIAogIHNlbGVjdChzaXRlLCBzZWFzb24sIGRveSwgbGF0LCB0ZW1wX2NoYW5nZSwgdmFyX2NoYW5nZSwgY3RtYXhfY2hhbmdlLCB3dF9jaGFuZ2UpCgpnZ3Bsb3QodmFyX2NoYW5nZV9kYXRhLCBhZXMoeCA9IHRlbXBfY2hhbmdlLCB5ID0gdmFyX2NoYW5nZSwgY29sb3VyID0gc2l0ZSkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiV2FybWluZyBUb2xlcmFuY2UgQ2hhbmdlICjCsEMpIiwKICAgICAgIHkgPSAiQ2hhbmdlIGluIENUbWF4IFZhcmlhbmNlIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKCmdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gc2l6ZV9yYW5nZSwgeSA9IHNpemVfdmFyKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpICsKICB0aGVtZV9tYXR0KCkKYGBgCgojIyBDb21wYXJpbmcgcmF0ZXMgb2YgY2hhbmdlCkJvdGggQ1RtYXggYW5kIGJvZHkgc2l6ZSB2YXJpZWQgYmV0d2VlbiBzaXRlcyBhbmQgYWNyb3NzIHNlYXNvbnMuIEl0IGNhbiBiZSBkaWZmaWN1bHQgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGVzZSB0d28gdHJhaXRzLiBXZSB0YWtlIHR3byBhcHByb2FjaGVzIHRvIGVhc2UgdGhpcyBjb21wYXJpc29uLiAKU2hvd24gYmVsb3cgaXMgYSBjb21wYXJpc29uIG9mIHRoZSBzbG9wZXMgZnJvbSB0aGUgdHJhaXQgcmVncmVzc2lvbnMgYWdhaW5zdCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGZvciBlYWNoIHBvcHVsYXRpb24sIHN0YW5kYXJkaXplZCBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSB0cmFpdCBmb3IgZWFjaCBwb3B1bGF0aW9uIChhY3Jvc3MgYWxsIGNvbGxlY3Rpb25zKS4gVGhpcyBwcmVzZW50cyBjaGFuZ2UgcGVyIGRlZ3JlZSBjaGFuZ2UgaW4gY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSBpbiB1bml0cyBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBib3RoIENUbWF4IGFuZCBib2R5IHNpemUuCgpgYGB7ciBhZGotc2xvcGUtY29tcCwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9Nn0KYWRqX3Nsb3BlcyA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgbGF0KSAlPiUgCiAgYXJyYW5nZShkb3kpICU+JSAgCiAgZmlsdGVyKHNpdGUgIT0gIktleSBMYXJnbyIpICU+JQogIHN1bW1hcml6ZSgiY3RtYXhfc2xvcGUiID0gY29lZihsbShjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCkpWyJjb2xsZWN0aW9uX3RlbXAiXSwgCiAgICAgICAgICAgICJtZWFuX2N0bWF4IiA9IG1lYW4oY3RtYXgpLAogICAgICAgICAgICAiY3RtYXhfc2QiID0gc2QoY3RtYXgpLAogICAgICAgICAgICAic2l6ZV9zbG9wZSIgPSBjb2VmKGxtKHNpemUgfiBjb2xsZWN0aW9uX3RlbXApKVsiY29sbGVjdGlvbl90ZW1wIl0sIAogICAgICAgICAgICAibWVhbl9zaXplIiA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgICJzaXplX3NkIiA9IHNkKHNpemUpLCAKICAgICAgICAgICAgInRlbXBfcmFuZ2UiID0gbWF4KGNvbGxlY3Rpb25fdGVtcCkgLSBtaW4oY29sbGVjdGlvbl90ZW1wKSkgJT4lICAKICBkcm9wX25hKCkgJT4lIAogIG11dGF0ZShhZGpfY3RtYXhfc2xvcGUgPSBjdG1heF9zbG9wZSAvIGN0bWF4X3NkLAogICAgICAgICBhZGpfc2l6ZV9zbG9wZSA9IHNpemVfc2xvcGUgLyBzaXplX3NkKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiX3Nsb3BlIiksIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJzbG9wZV90eXBlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInNsb3BlIikKCiMgZ2dwbG90KGFkal9zbG9wZXMsIGFlcyh4ID0gbGF0LCB5ID0gdGVtcF9yYW5nZSkpICsgCiMgICBnZW9tX3BvaW50KCkgKyAKIyAgIHRoZW1lX21hdHQoKQoKZ2dwbG90KGZpbHRlcihhZGpfc2xvcGVzLCBzdHJfZGV0ZWN0KHNsb3BlX3R5cGUsICJhZGpfIikpLCBhZXMoeCA9IHNsb3BlX3R5cGUsIHkgPSBhYnMoc2xvcGUpLCAKICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IHNpdGUsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh4ID0gIiIsIAogICAgICAgeSA9ICJTbG9wZSAoYWJzb2x1dGUgdmFsdWUpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKYGBgCgpIYWxkYW5lcyBhcmUgYSBzaW1pbGFyIHVuaXQsIHJlcHJlc2VudGluZyBjaGFuZ2UgaW4gdW5pdHMgb2Ygc3RhbmRhcmQgZGV2aWF0aW9ucyBwZXIgZ2VuZXJhdGlvbi4gVGhpcyBjYW4gYmUgYSB1c2VmdWwgbWV0cmljIGZvciBjb21wYXJpbmcgYWNyb3NzIHRyYWl0cywgZXNwZWNpYWxseSBhcyB0aGUgbnVtYmVyIG9mIGdlbmVyYXRpb25zIGNvdmVyZWQgYnkgb3VyIHNhbXBsaW5nIHBlcmlvZCBsaWtlbHkgdmFyaWVzIGFjcm9zcyBwb3B1bGF0aW9ucy4gVGhlIGNhbGN1bGF0aW9uIG9mIGhhbGRhbmVzIGlzIHRha2VuIGZyb20gSGVuZHJ5IGFuZCBLaW5uaXNvbiAoMTk5OSksIHdoaWNoIGluIHR1cm4gaXMgYmFzZWQgb24gd29yayBmcm9tIEdpbmdlcmljaCAoMTk5MykuIFdlIGVzdGltYXRlZCB0aGUgbnVtYmVyIG9mIGdlbmVyYXRpb25zIHBhc3NlZCBiZXR3ZWVuIGNvbGxlY3Rpb25zIHVzaW5nIHRoZSBlbXBpcmljYWwgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIGRldmVsb3BtZW50IHRpbWUgZm9yICpBY2FydGlhIHRvbnNhKiBmcm9tIExlYW5kcm8gZXQgYWwuICgyMDA2KS4gRm9yIGluaXRpYWwgZXN0aW1hdGVzLCB3ZSB1c2VkIGEgdGVtcGVyYXR1cmUgaGFsZndheSBiZXR3ZWVuIHdoYXQgd2FzIG9ic2VydmVkIGR1cmluZyBjb2xsZWN0aW9uLiBDaGFuZ2VzIHdlcmUgZXhhbWluZWQgZm9yIGVhY2ggcGFpciBvZiBjb2xsZWN0aW9ucyAoZWFybHkgdG8gcGVhaywgYW5kIHBlYWsgdG8gbGF0ZSkuICAgIAoKU2hvd24gYmVsb3cgaXMgYSBjb21wYXJpc29uIG9mIHRoZSBlc3RpbWF0ZWQgaGFsZGFuZSB2YWx1ZXMgZm9yIENUbWF4IGFuZCBib2R5IHNpemUsIHNlcGFyYXRlZCBieSBzZWFzb24uIEtlZXAgaW4gbWluZCB0aGF0IHdoaWxlIHRoaXMgbWV0cmljIGFjY291bnRzIGZvciBkaWZmZXJlbmNlcyBpbiB0aGUgbnVtYmVyIG9mIGdlbmVyYXRpb25zIGJldHdlZW4gY29sbGVjdGlvbnMsIGl0IGRvZXMgbm90IGRpcmVjdGx5IGFjY291bnQgZm9yIGRpZmZlcmVuY2VzIGluIHRlbXBlcmF0dXJlLCBsZWFkaW5nIHRvIGluZmxhdGVkIHZhbHVlcyBpbiB0aGUgInBlYWsgdG8gbGF0ZSIgY29tcGFyaXNvbnMsIHdoaWNoIHR5cGljYWxseSBjb3ZlcmVkIGEgbGFyZ2VyIHJhbmdlIG9mIHRlbXBlcmF0dXJlcy4gCgpgYGB7ciBoYWxkYW5lLWNvbXAtcGxvdCwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD05fQplYXJseV9wZWFrID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc2Vhc29uICVpbiUgYygiZWFybHkiLCAicGVhayIpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9IGlmX2Vsc2Uoc2Vhc29uID09ICJlYXJseSIsICJvbmUiLCAidHdvIikpICU+JSAKICBncm91cF9ieShzaXRlKSAlPiUgCiAgbXV0YXRlKGN0bWF4X3NkX3AgPSBzZChjdG1heCksCiAgICAgICAgIHNpemVfc2RfcCA9IHNkKHNpemUpLCAKICAgICAgICAgdGVtcF9jaGFuZ2UgPSBtYXgoY29sbGVjdGlvbl90ZW1wKSAtIG1pbihjb2xsZWN0aW9uX3RlbXApLAogICAgICAgICBhdmdfdGVtcCA9IChtYXgoY29sbGVjdGlvbl90ZW1wKSArIG1pbihjb2xsZWN0aW9uX3RlbXApKSAvIDIsCiAgICAgICAgIGRheXNfcGFzc2VkID0gbWF4KGRveSkgLSBtaW4oZG95KSkgJT4lIAogIHNlbGVjdChzaXRlLCBsYXQsIHNlYXNvbiwgCiAgICAgICAgIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQsIAogICAgICAgICBjdG1heCwgc2l6ZSkgJT4lCiAgZ3JvdXBfYnkoc2l0ZSwgbGF0LCBzZWFzb24sIAogICAgICAgICAgIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCkgJT4lIAogIHN1bW1hcml6ZShjdG1heCA9IG1lYW4oY3RtYXgpLAogICAgICAgICAgICBzaXplID0gbWVhbihzaXplKSkgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKHNpdGUsIGxhdCwgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IHNlYXNvbiwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBjKGN0bWF4LCBzaXplKSkgJT4lIAogIG11dGF0ZShzZWFzb24gPSAiZWFybHlfdG9fcGVhayIpICU+JSAgCiAgZHJvcF9uYSgpCgpwZWFrX2xhdGUgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZWFzb24gJWluJSBjKCJwZWFrIiwgImxhdGUiKSkgJT4lIAogIG11dGF0ZShzZWFzb24gPSBpZl9lbHNlKHNlYXNvbiA9PSAicGVhayIsICJvbmUiLCAidHdvIikpICU+JSAKICBncm91cF9ieShzaXRlKSAlPiUgCiAgbXV0YXRlKGN0bWF4X3NkX3AgPSBzZChjdG1heCksCiAgICAgICAgIHNpemVfc2RfcCA9IHNkKHNpemUpLCAKICAgICAgICAgdGVtcF9jaGFuZ2UgPSBsYXN0KGNvbGxlY3Rpb25fdGVtcCkgLSBmaXJzdChjb2xsZWN0aW9uX3RlbXApLAogICAgICAgICBhdmdfdGVtcCA9IChtYXgoY29sbGVjdGlvbl90ZW1wKSArIG1pbihjb2xsZWN0aW9uX3RlbXApKSAvIDIsCiAgICAgICAgIGRheXNfcGFzc2VkID0gbWF4KGRveSkgLSBtaW4oZG95KSkgJT4lIAogIHNlbGVjdChzaXRlLCBsYXQsIHNlYXNvbiwgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCwgCiAgICAgICAgIGN0bWF4LCBzaXplKSAlPiUKICBncm91cF9ieShzaXRlLCBsYXQsIHNlYXNvbiwgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkKSAlPiUgCiAgc3VtbWFyaXplKGN0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIHNpemUgPSBtZWFuKHNpemUpKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoc2l0ZSwgbGF0LCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc2Vhc29uLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMoY3RtYXgsIHNpemUpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9ICJwZWFrX3RvX2xhdGUiKSAlPiUgIAogIGRyb3BfbmEoKQoKY2FsY19oYWxkcyA9IGZ1bmN0aW9uKHgxLCB4Miwgc2RfcCwgZyl7CiAgKCh4MiAvIHNkX3ApIC0gKHgxIC8gc2RfcCkpIC8gZwp9CgpoYWxkYW5lcyA9IGJpbmRfcm93cyhlYXJseV9wZWFrLCBwZWFrX2xhdGUpICU+JSAKICBtdXRhdGUoImdlbl90aW1lIiA9IDU0OTAqKGF2Z190ZW1wICsgMSleLTIuMDUsIAogICAgICAgICAiZ2VucyIgPSBmbG9vcihkYXlzX3Bhc3NlZCAvIGdlbl90aW1lKSwKICAgICAgICAgImN0bWF4X2hhbGRhbmVzIiA9IGNhbGNfaGFsZHMoeDIgPSBjdG1heF90d28sIHgxID0gY3RtYXhfb25lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RfcCA9IGN0bWF4X3NkX3AsIGcgPSBnZW5zKSwKICAgICAgICAgInNpemVfaGFsZGFuZXMiID0gY2FsY19oYWxkcyh4MiA9IHNpemVfdHdvLCB4MSA9IHNpemVfb25lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9wID0gc2l6ZV9zZF9wLCBnID0gZ2VucykpCgpoYWxkYW5lcyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3Qoc2l0ZSwgdGVtcF9jaGFuZ2UsIHNlYXNvbiwgY3RtYXhfaGFsZGFuZXMsIHNpemVfaGFsZGFuZXMpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoY3RtYXhfaGFsZGFuZXMsIHNpemVfaGFsZGFuZXMpLAogICAgICAgICAgICAgICBuYW1lc190byA9IGMoInR5cGUiLCBOQSksIAogICAgICAgICAgICAgICBuYW1lc19zZXAgPSAiXyIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJoYWxkYW5lcyIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB0eXBlLCB5ID0gaGFsZGFuZXMsIGdyb3VwID0gc2l0ZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZmFjZXRfd3JhcChzZWFzb25+LikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fbGluZShhZXMobGluZXdpZHRoID0gZGVzYyh0ZW1wX2NoYW5nZSkpKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJUcmFpdCIsIAogICAgICAgeSA9ICJIYWxkYW5lcyIsIAogICAgICAgbGluZXdpZHRoID0gIlRlbXAuIENoYW5nZSIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKCgpgYGB7ciBoYWxkYW5lLXJlc2lkcy1jb21wLXBsb3QsIGZpZy5oZWlnaHQ9My41LCBmaWcud2lkdGg9OSwgaW5jbHVkZSA9IEZ9CmVhcmx5X3BlYWtfcmVzaWRzID0gdW5pdmVyc2FsX3Jlc2lkcyAlPiUgCiAgZmlsdGVyKHNlYXNvbiAlaW4lIGMoImVhcmx5IiwgInBlYWsiKSkgJT4lIAogIG11dGF0ZShzZWFzb24gPSBpZl9lbHNlKHNlYXNvbiA9PSAiZWFybHkiLCAib25lIiwgInR3byIpKSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSkgJT4lIAogIG11dGF0ZShjdG1heF9zZF9wID0gc2QoY3RtYXhfcmVzaWRzKSwKICAgICAgICAgc2l6ZV9zZF9wID0gc2Qoc2l6ZV9yZXNpZHMpLCAKICAgICAgICAgdGVtcF9jaGFuZ2UgPSBtYXgoY29sbGVjdGlvbl90ZW1wKSAtIG1pbihjb2xsZWN0aW9uX3RlbXApLAogICAgICAgICBhdmdfdGVtcCA9IChtYXgoY29sbGVjdGlvbl90ZW1wKSArIG1pbihjb2xsZWN0aW9uX3RlbXApKSAvIDIsCiAgICAgICAgIGRheXNfcGFzc2VkID0gbWF4KGRveSkgLSBtaW4oZG95KSkgJT4lIAogIHNlbGVjdChzaXRlLCBsYXQsIHNlYXNvbiwgCiAgICAgICAgIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQsIAogICAgICAgICBjdG1heF9yZXNpZHMsIHNpemVfcmVzaWRzKSAlPiUKICBncm91cF9ieShzaXRlLCBsYXQsIHNlYXNvbiwgCiAgICAgICAgICAgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkKSAlPiUgCiAgc3VtbWFyaXplKGN0bWF4ID0gbWVhbihjdG1heF9yZXNpZHMpLAogICAgICAgICAgICBzaXplID0gbWVhbihzaXplX3Jlc2lkcykpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhzaXRlLCBsYXQsIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCksIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzZWFzb24sIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYyhjdG1heCwgc2l6ZSkpICU+JSAKICBtdXRhdGUoc2Vhc29uID0gImVhcmx5X3RvX3BlYWsiKSAlPiUgIAogIGRyb3BfbmEoKQoKcGVha19sYXRlX3Jlc2lkcyA9IHVuaXZlcnNhbF9yZXNpZHMgJT4lIAogIGZpbHRlcihzZWFzb24gJWluJSBjKCJwZWFrIiwgImxhdGUiKSkgJT4lIAogIG11dGF0ZShzZWFzb24gPSBpZl9lbHNlKHNlYXNvbiA9PSAicGVhayIsICJvbmUiLCAidHdvIikpICU+JSAKICBncm91cF9ieShzaXRlKSAlPiUgCiAgbXV0YXRlKGN0bWF4X3NkX3AgPSBzZChjdG1heF9yZXNpZHMpLAogICAgICAgICBzaXplX3NkX3AgPSBzZChzaXplX3Jlc2lkcyksIAogICAgICAgICB0ZW1wX2NoYW5nZSA9IGxhc3QoY29sbGVjdGlvbl90ZW1wKSAtIGZpcnN0KGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgIGF2Z190ZW1wID0gKG1heChjb2xsZWN0aW9uX3RlbXApICsgbWluKGNvbGxlY3Rpb25fdGVtcCkpIC8gMiwKICAgICAgICAgZGF5c19wYXNzZWQgPSBtYXgoZG95KSAtIG1pbihkb3kpKSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkLCAKICAgICAgICAgY3RtYXhfcmVzaWRzLCBzaXplX3Jlc2lkcykgJT4lCiAgZ3JvdXBfYnkoc2l0ZSwgbGF0LCBzZWFzb24sIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCkgJT4lIAogIHN1bW1hcml6ZShjdG1heCA9IG1lYW4oY3RtYXhfcmVzaWRzKSwKICAgICAgICAgICAgc2l6ZSA9IG1lYW4oc2l6ZV9yZXNpZHMpKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoc2l0ZSwgbGF0LCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc2Vhc29uLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMoY3RtYXgsIHNpemUpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9ICJwZWFrX3RvX2xhdGUiKSAlPiUgIAogIGRyb3BfbmEoKQoKY2FsY19oYWxkcyA9IGZ1bmN0aW9uKHgxLCB4Miwgc2RfcCwgZyl7CiAgKCh4MiAvIHNkX3ApIC0gKHgxIC8gc2RfcCkpIC8gZwp9CgpoYWxkYW5lc19yZXNpZHMgPSBiaW5kX3Jvd3MoZWFybHlfcGVha19yZXNpZHMsIHBlYWtfbGF0ZV9yZXNpZHMpICU+JSAKICBtdXRhdGUoImdlbl90aW1lIiA9IDU0OTAqKGF2Z190ZW1wICsgMSleLTIuMDUsIAogICAgICAgICAiZ2VucyIgPSBmbG9vcihkYXlzX3Bhc3NlZCAvIGdlbl90aW1lKSwKICAgICAgICAgImN0bWF4X2hhbGRhbmVzIiA9IGNhbGNfaGFsZHMoeDIgPSBjdG1heF90d28sIHgxID0gY3RtYXhfb25lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RfcCA9IGN0bWF4X3NkX3AsIGcgPSBnZW5zKSwKICAgICAgICAgInNpemVfaGFsZGFuZXMiID0gY2FsY19oYWxkcyh4MiA9IHNpemVfdHdvLCB4MSA9IHNpemVfb25lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9wID0gc2l6ZV9zZF9wLCBnID0gZ2VucykpCgpoYWxkYW5lc19yZXNpZHMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KHNpdGUsIHRlbXBfY2hhbmdlLCBzZWFzb24sIGN0bWF4X2hhbGRhbmVzLCBzaXplX2hhbGRhbmVzKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGN0bWF4X2hhbGRhbmVzLCBzaXplX2hhbGRhbmVzKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSBjKCJ0eXBlIiwgTkEpLCAKICAgICAgICAgICAgICAgbmFtZXNfc2VwID0gIl8iLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiaGFsZGFuZXMiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSwgeSA9IGhhbGRhbmVzLCBncm91cCA9IHNpdGUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoc2Vhc29ufi4pICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2xpbmUoYWVzKGxpbmV3aWR0aCA9IGRlc2ModGVtcF9jaGFuZ2UpKSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiVHJhaXQiLCAKICAgICAgIHkgPSAiSGFsZGFuZXMiLCAKICAgICAgIGxpbmV3aWR0aCA9ICJUZW1wLiBDaGFuZ2UiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKYGBgCgpTaG93biBiZWxvdyBhcmUgdGhlIGhhbGRhbmUgdmFsdWVzIHBsb3R0ZWQgYWdhaW5zdCBsYXRpdHVkZS4gTm90ZSB0aGF0IGV2ZW4gdGhvdWdoIGxhcmdlIGNoYW5nZXMgaW4gdGVtcGVyYXR1cmUgb2NjdXJlZCBiZXR3ZWVuIHBlYWsgYW5kIGxhdGUgc2FtcGxlcyBpbiB0aGUgQ2hlc2FwZWFrZSwgdGhlIGNoYW5nZSBpbiBoYWxkYW5lcyBpcyByZWxhdGl2ZWx5IHNtYWxsLCB3aGlsZSBpbiB0aGUgTm9ydGhlcm4gcG9wdWxhdGlvbnMsIGNoYW5nZXMgYXJlIGxhcmdlciwgdGhvdWdoIG1vcmUgdmFyaWFibGUuIAoKYGBge3IgaGFsZGFuZXMtbGF0LXBsb3QsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD04fQpjdG1heF9oYWxkYW5lcyA9IGdncGxvdChoYWxkYW5lcywgYWVzKHggPSBsYXQsIHkgPSBjdG1heF9oYWxkYW5lcywgY29sb3VyID0gc2l0ZSwgc2hhcGUgPSBzZWFzb24pKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLAogICAgICAgeSA9ICJDaGFuZ2UgaW4gQ1RtYXggKGhhbGRhbmVzKSIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQoKc2l6ZV9oYWxkYW5lcyA9IGdncGxvdChoYWxkYW5lcywgYWVzKHggPSBsYXQsIHkgPSBzaXplX2hhbGRhbmVzLCBjb2xvdXIgPSBzaXRlLCBzaGFwZSA9IHNlYXNvbikpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJMYXRpdHVkZSIsCiAgICAgICB5ID0gIkNoYW5nZSBpbiBTaXplIChoYWxkYW5lcykiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKCmdnYXJyYW5nZShjdG1heF9oYWxkYW5lcywgc2l6ZV9oYWxkYW5lcywgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIsIG5yb3cgPSAyKQpgYGAKCiMjIFdoeSBkb2VzIGludHJhc3BlY2lmaWMgZGF0YSBtYXR0ZXI/IApgYGB7cn0KIyBDb21wYXJlIGVzdGltYXRlZCB3YXJtaW5nIHRvbGVyYW5jZSAicmFuZ2VzIiB3aGVuOiAxKSBDVG1heCBmb3IgImF2ZXJhZ2UiIGNvbGxlY3Rpb24gaXMgdXNlZDsgMikgV2hlbiBDVG1heCBmb3Igb25lIGNvbGxlY3Rpb24gcGVyIHBvcHVsYXRpb24gaXMgdXNlZDsgYW5kIDMpIFdoZW4gYWxsIGNvbGxlY3Rpb25zIGFyZSB1c2VkLiBUaGUgaWRlYSBpcyB0byBzaG93IHRoYXQgbm90IGFjY291bnRpbmcgZm9yIGludHJhLXNwZWNpZmljIGFuZCBpbnRyYS1wb3B1bGF0aW9uIHZhcmlhdGlvbiBsZWFkcyB0byBpbmNvcnJlY3QgcHJlZGljdGlvbnMgb2YgdnVsbmVyYWJpbGl0eSB0byB3YXJtaW5nIGJlY2F1c2UgdGhpcyB2YXJpYXRpb24gY2FuIGJlIHN1YnN0YW50aWFsIC0gYWNyb3NzIHBvcHVsYXRpb25zIHdpdGhpbiBlYWNoIHNlYXNvbmFsIGNvbGxlY3Rpb24sIHRoZXJlIGlzIGF0IGxlYXN0IDXCsEMgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzLCB3aGlsZSBhY3Jvc3MgY29sbGVjdGlvbnMgd2l0aGluIHBvcHVsYXRpb25zLCBhY2NsaW1hdGlvbiB0byBjaGFuZ2VzIGluIHRlbXBlcmF0dXJlIGNhbiBkcml2ZSBzdWJzdGFudGlhbCB2YXJpYXRpb24uIAoKIyMgU2NlbmFyaW8gMSAtIHNpbmdsZSBwb2ludCBlc3RpbWF0ZXMgCgplc3RfMSA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uKSAlPiUgCiAgc3VtbWFyaXNlKCJtZWFuX2N0bWF4IiA9IG1lYW4oY3RtYXgpKSAlPiUgCiAgZmlsdGVyKHNpdGUgPT0gIlR5bGVyIENvdmUiLCBzZWFzb24gPT0gInBlYWsiKQoKc2NlbmFyaW9fMSA9IGZ1bGxfZGF0YSAlPiUgCiAgbXV0YXRlKHJlcF9jdG1heCA9IGVzdF8xJG1lYW5fY3RtYXgsCiAgICAgICAgIHByZWRfd3QgPSByZXBfY3RtYXggLSBjb2xsZWN0aW9uX3RlbXAsIAogICAgICAgICB3dF9kaWZmID0gcHJlZF93dCAtIHdhcm1pbmdfdG9sKQogIApnZ3Bsb3Qoc2NlbmFyaW9fMSwgYWVzKHggPSBsYXQsIHkgPSB3dF9kaWZmKSkgKyAKICBmYWNldF93cmFwKHNlYXNvbn4uLCBucm93ID0gMykgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fcG9pbnQoKSArIAogIGxhYnMoeCA9ICJMYXRpdHVkZSIsIAogICAgICAgeSA9ICJQcmVkaWN0ZWQgLSBPYnNlcnZlZCBXVCIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKCgoKIyMgTmV4dCBTdGVwcwoKQWZ0ZXIgcGhlbm90eXBpbmcsIGVhY2ggaW5kaXZpZHVhbCB3YXMgcHJlc2VydmVkIGluIDk1JSBldGhhbm9sLiBJbmRpdmlkdWFsIEROQSBsaWJyYXJpZXMgd2lsbCBiZSBwcmVwYXJlZCB1c2luZyBUd2lzdCBCaW8gOTYtcGxleCBwcmVwIGtpdHMsIHRoZW4gc2VxdWVuY2VkIG9uIGFuIElsbHVtaW5hIE5vdmFTZXEgWCBQbHVzLiBVc2luZyB0aGUgbG93LWNvdmVyYWdlIHdob2xlIGdlbm9tZSBzZXF1ZW5jZXMsIHdlIHdpbGwgZXhhbWluZSBzZWFzb25hbCBwYXR0ZXJucyBpbiBhbGxlbGUgZnJlcXVlbmN5IGNoYW5nZSwgYW5kIGNvbXBhcmUgdGhlc2UgZmluZSBzY2FsZSB0ZW1wb3JhbCBwYXR0ZXJucyB3aXRoIHRoZSBsYXJnZXIgbGF0aXR1ZGluYWwgcGF0dGVybnMgaW4gYWxsZWxlIGZyZXF1ZW5jeSB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgc2FtZSBhbGxlbGVzIGRyaXZpbmcgcmFwaWQgc2Vhc29uYWwgYWRhcHRhdGlvbiBhcmUgaW4gcGxheSBvdmVyIGxhcmdlciBzcGF0aWFsIChhbmQgbG9uZ2VyIHRlbXBvcmFsKSBzY2FsZXMuCgojIyBNaXNjLiBEZXRhaWxzCgpgYGB7ciB0ZW1wLXJlY29yZC1wbG90LCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQpnZ3Bsb3QodGVtcF9yZWNvcmQsIGFlcyh4ID0gbWludXRlX3Bhc3NlZCwgeSA9IHRlbXBfQywgZ3JvdXAgPSBmYWN0b3IocnVuKSkpICsgCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAwLjMsIGludGVyY2VwdCA9IG1lYW4odGVtcF9yZWNvcmRbdGVtcF9yZWNvcmQkbWludXRlX2ludGVydmFsID09IDAsIDhdKSkgKyAKICBnZW9tX2FibGluZShzbG9wZSA9IDAuMSwgaW50ZXJjZXB0ID0gbWVhbih0ZW1wX3JlY29yZFt0ZW1wX3JlY29yZCRtaW51dGVfaW50ZXJ2YWwgPT0gMCwgOF0pKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjIsIGFscGhhID0gMC44KSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZ1bGxfZGF0YSwgCiAgICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBjdG1heCArIDAuNCksCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIHNoYXBlID0gMjUpICsKICBsYWJzKHggPSAiVGltZSBwYXNzZWQgKG1pbnV0ZXMpIiwKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKGRlZ3JlZXMgQykiLAogICAgICAgZmlsbCA9ICJUcmlhbCBOdW1iZXIiKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyIHJhbXAtcmVjb3JkLXBsb3QsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9CnJhbXBfcmVjb3JkMiA9IHJhbXBfcmVjb3JkICU+JSAKICBncm91cF9ieShydW4sIG1pbnV0ZV9pbnRlcnZhbCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3JhbXAgPSBtZWFuKHJhbXBfcGVyX21pbnV0ZSkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChyYW1wX3JlY29yZDIsIGFlcyh4ID0gbWludXRlX2ludGVydmFsLCB5ID0gbWVhbl9yYW1wKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjMpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4xKSArIAogICNnZW9tX3BvaW50KCkgKyAKICBnZW9tX2hleChiaW5zID0gMzApICsgCiAgeWxpbSgwLCAwLjM1KSArIAogIGxhYnMoeSA9ICJSYW1wIFJhdGUgKGRlZy4gQyAvIG1pbi4pIiwKICAgICAgIHggPSAiVGltZSBpbnRvIHJ1biAobWludXRlKSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgCmBgYAoKYGBge3IgcmVwLWNvbXAsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04fQpmdWxsX2RhdGEgJT4lIAogIGRyb3BfbmEocmVwbGljYXRlKSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGZhY3RvcihyZXBsaWNhdGUpLCB5ID0gY3RtYXgsIGdyb3VwID0gc2l0ZSkpICsgCiAgZmFjZXRfZ3JpZChzaXRlfnNlYXNvbiwgc2NhbGVzID0gImZyZWVfeSIpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMSwgaGVpZ2h0ID0gMCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuNCwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5MzAiKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJibGFjayIpICsgCiAgbGFicyh4ID0gIlJlcGxpY2F0ZSIsIAogICAgICAgeSA9ICJDVG1heCIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKCmBgYHtyIG51bS1nZW5zLXBsb3QsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03fQpnZ3Bsb3QoaGFsZGFuZXMsIGFlcyh4ID0gbGF0LCB5ID0gZ2VucywgY29sb3VyID0gc2l0ZSwgc2hhcGUgPSBzZWFzb24pKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLCAKICAgICAgIHkgPSAiR2VuZXJhdGlvbnMgYmV0d2VlbiBcbmNvbGxlY3Rpb25zIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoZnJvbSA9IDAsIHRvID0gMTEsIGJ5ID0gMikpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpgYGB7ciByYW5rLXNpbXMsIGZpZy53aWR0aD0xOCwgZmlnLmhlaWdodD04fQpvYnNfcmFua3MgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHJhbmspKSArIAogIGZhY2V0X3dyYXAodHViZX4uKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygyLDQsNiw4LDEwKSkgKyAKICBnZ3RpdGxlKCJPYnNlcnZhdGlvbiIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQoKc2ltX2RhdGEgPSBkYXRhLmZyYW1lKCkKZm9yKGkgaW4gMTptYXgoZnVsbF9kYXRhJHJ1bikpewogIHJlcF9kYXRhID0gZGF0YS5mcmFtZSgidHViZSIgPSBzYW1wbGUoYygxOjEwKSwgc2l6ZSA9IDEwLCByZXBsYWNlID0gRiksIAogICAgICAgICAgICJyYW5rIiA9IGMoMToxMCksCiAgICAgICAgICAgInJlcCIgPSBpKSAlPiUgCiAgYXJyYW5nZSh0dWJlKQogIAogIHNpbV9kYXRhID0gYmluZF9yb3dzKHNpbV9kYXRhLCByZXBfZGF0YSkKICAKfQoKc2ltX3JhbmtzID0gZ2dwbG90KHNpbV9kYXRhLCBhZXMoeCA9IHJhbmspKSArIAogIGZhY2V0X3dyYXAodHViZX4uKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygyLDQsNiw4LDEwKSkgKyAKICBnZ3RpdGxlKCJTaW11bGF0aW9uIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCgoKZ2dhcnJhbmdlKG9ic19yYW5rcywgc2ltX3JhbmtzKQpgYGAKCg==